Salome HOME
Improvement: Bug PAL10401 wrong sens in cut line
[modules/visu.git] / src / VISU_I / VISU_CutLines_i.cc
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_PrsObject_i.cxx
24 //  Author : Alexey PETROV
25 //  Module : VISU
26
27 #include "VISU_CutLinesPL.hxx"
28 #include "VISU_Result_i.hh"
29 #include "VISU_CutLines_i.hh"
30 #include "VISU_Actor.h"
31
32 #include "VISU_PipeLineUtils.hxx"
33
34 #include <vtkAppendPolyData.h>
35
36 using namespace VISU;
37 using namespace std;
38
39 static float EPS_machine = 1.0E-7;
40
41 #ifdef _DEBUG_
42 static int MYDEBUG = 0;
43 #else
44 static int MYDEBUG = 0;
45 #endif
46
47 int VISU::CutLines_i::IsPossible(Result_i* theResult, const char* theMeshName, VISU::Entity theEntity, 
48                                  const char* theFieldName, int theIteration, int isMemoryCheck)
49 {
50   return VISU::ScalarMap_i::IsPossible(theResult,theMeshName,theEntity,theFieldName,theIteration,isMemoryCheck);
51 }
52
53 int VISU::CutLines_i::myNbPresent = 0;
54 QString VISU::CutLines_i::GenerateName() { return VISU::GenerateName("CutLines",myNbPresent++);}
55
56 const string VISU::CutLines_i::myComment = "CUTLINES";
57 const char* VISU::CutLines_i::GetComment() const { return myComment.c_str();}
58
59
60 VISU::CutLines_i::
61 CutLines_i(Result_i* theResult, 
62            bool theAddToStudy) :
63   PrsObject_i(theResult->GetStudyDocument()), 
64   Prs3d_i(theResult,theAddToStudy),
65   ScalarMap_i(theResult,theAddToStudy),
66   myCutLinesPL(NULL)
67 {
68 }
69
70
71 VISU::CutLines_i::
72 CutLines_i(Result_i* theResult, 
73            SALOMEDS::SObject_ptr theSObject) :
74   PrsObject_i(theResult->GetStudyDocument()), 
75   Prs3d_i(theResult,theSObject),
76   ScalarMap_i(theResult,theSObject),
77   myCutLinesPL(NULL)
78 {
79 }
80
81
82 void VISU::CutLines_i::SameAs(const CutLines_i* theOrigin){
83   VISU::ScalarMap_i::SameAs(theOrigin);
84 }
85
86 /*! Copy map to /a myMapCurvesInverted.
87  * \param theCurves - map
88  */
89 void VISU::CutLines_i::CopyCurvesInverted(const TCurvesInv& theCurves){
90   myMapCurvesInverted = theCurves;
91 }
92
93 VISU::Storable* VISU::CutLines_i::Create(const char* theMeshName, VISU::Entity theEntity, 
94                                          const char* theFieldName, int theIteration)
95 {
96   return ScalarMap_i::Create(theMeshName,theEntity,theFieldName,theIteration);
97 }
98
99
100 VISU::Storable* VISU::CutLines_i::Restore(const Storable::TRestoringMap& theMap)
101 {
102   DoHook();
103   SetNbLines(VISU::Storable::FindValue(theMap,"myNbLines").toInt());
104   SetDisplacement(VISU::Storable::FindValue(theMap,"myDisplacement[0]").toDouble());
105   SetDisplacement2(VISU::Storable::FindValue(theMap,"myDisplacement[1]").toDouble());
106   SetOrientation(CutPlanes::Orientation(VISU::Storable::FindValue(theMap,"myBasePlane[0]").toInt()),
107                  Storable::FindValue(theMap,"aRot[0][0]").toDouble(),
108                  Storable::FindValue(theMap,"aRot[0][1]").toDouble());
109   SetOrientation2(CutPlanes::Orientation(VISU::Storable::FindValue(theMap,"myBasePlane[1]").toInt()),
110                   Storable::FindValue(theMap,"aRot[1][0]").toDouble(),
111                   Storable::FindValue(theMap,"aRot[1][1]").toDouble());
112   if (VISU::Storable::FindValue(theMap,"myBasePlaneCondition").toInt())
113     SetDefault();
114   else
115     SetBasePlanePosition(VISU::Storable::FindValue(theMap,"myBasePlanePosition").toDouble());
116   
117   QStringList aPosList = QStringList::split("|",VISU::Storable::FindValue(theMap,"myLinePosition") );
118   QStringList aCondList = QStringList::split("|",VISU::Storable::FindValue(theMap,"myLineCondition") );
119   for(int i = 0, iEnd = GetNbLines(); i < iEnd; i++)
120     if(aCondList[i].toInt() == 0)
121       SetLinePosition(i,aPosList[i].toDouble());
122
123   // Restoring the map - \a myMapCurvesInverted
124   QStringList aMapCurvesInverted = QStringList::split("|",VISU::Storable::FindValue(theMap,"myMapCurvesInverted") );
125   if (aMapCurvesInverted.count() == GetNbLines()){
126     for(int i = 0, iEnd = GetNbLines(); i < iEnd ; i++){
127       if(aMapCurvesInverted[i].toInt())
128         SetCurveInverted(i,true);
129       else
130         SetCurveInverted(i,false);
131     }
132   } else {
133     for(int i = 0, iEnd = GetNbLines(); i < iEnd ; i++)
134       SetCurveInverted(i,false);
135   }
136       
137   return ScalarMap_i::Restore(theMap);
138 }
139
140
141 void VISU::CutLines_i::ToStream(std::ostringstream& theStr){
142   ScalarMap_i::ToStream(theStr);
143
144   int aNbLines = GetNbLines();
145   
146   Storable::DataToStream( theStr, "myNbLines",         aNbLines );
147   Storable::DataToStream( theStr, "myDisplacement[0]", GetDisplacement() );
148   Storable::DataToStream( theStr, "myDisplacement[1]", GetDisplacement2() );
149   Storable::DataToStream( theStr, "myBasePlane[0]",    int(GetOrientationType()) );
150   Storable::DataToStream( theStr, "myBasePlane[1]",    int(GetOrientationType2()) );
151   Storable::DataToStream( theStr, "aRot[0][0]",        GetRotateX() );
152   Storable::DataToStream( theStr, "aRot[0][1]",        GetRotateY() );
153   Storable::DataToStream( theStr, "aRot[1][0]",        GetRotateX2() );
154   Storable::DataToStream( theStr, "aRot[1][1]",        GetRotateY2() );
155   Storable::DataToStream( theStr, "myBasePlanePosition", GetBasePlanePosition() );
156   Storable::DataToStream( theStr, "myBasePlaneCondition", IsDefault() );
157
158   QString aStrPos, aStrCon;
159   for(int i = 0, iEnd = GetNbLines(); i < iEnd; i++){
160     aStrPos.append(QString::number(GetLinePosition(i)) + "|");
161     aStrCon.append(QString::number(IsDefaultPosition(i)) + "|");
162   }
163   Storable::DataToStream( theStr, "myLinePosition",  aStrPos.latin1());
164   Storable::DataToStream( theStr, "myLineCondition", aStrCon.latin1());
165
166   // Storing the map - \a myMapCurvesInverted
167   QString aStrCurvesInverted;
168   for(int i = 0, iEnd = GetNbLines(); i < iEnd; i++) 
169     aStrCurvesInverted.append(QString::number(IsCurveInverted(i)) + "|");
170   Storable::DataToStream( theStr, "myMapCurvesInverted", aStrCurvesInverted.latin1());
171 }
172
173 VISU::CutLines_i::~CutLines_i(){
174   if(MYDEBUG) MESSAGE("CutLines_i::~CutLines_i()");
175 }
176
177
178 void VISU::CutLines_i::SetOrientation(VISU::CutPlanes::Orientation theOrient,
179                                       CORBA::Double theXAngle, CORBA::Double theYAngle)
180 {
181   myCutLinesPL->SetOrientation(VISU_CutPlanesPL::PlaneOrientation(theOrient),
182                                theXAngle,theYAngle);
183 }
184 void VISU::CutLines_i::SetOrientation2(VISU::CutPlanes::Orientation theOrient,
185                                        CORBA::Double theXAngle, CORBA::Double theYAngle)
186 {
187   myCutLinesPL->SetOrientation(VISU_CutPlanesPL::PlaneOrientation(theOrient),
188                                theXAngle,theYAngle,1);
189 }
190
191 VISU::CutPlanes::Orientation VISU::CutLines_i::GetOrientationType() { 
192   return VISU::CutPlanes::Orientation(myCutLinesPL->GetPlaneOrientation());
193 }
194 VISU::CutPlanes::Orientation VISU::CutLines_i::GetOrientationType2() { 
195   return VISU::CutPlanes::Orientation(myCutLinesPL->GetPlaneOrientation(1));
196 }
197
198 CORBA::Double VISU::CutLines_i::GetRotateX(){
199   return myCutLinesPL->GetRotateX();
200 }
201 CORBA::Double VISU::CutLines_i::GetRotateY(){
202   return myCutLinesPL->GetRotateY();
203 }
204
205 CORBA::Double VISU::CutLines_i::GetRotateX2(){
206   return myCutLinesPL->GetRotateX(1);
207 }
208 CORBA::Double VISU::CutLines_i::GetRotateY2(){
209   return myCutLinesPL->GetRotateY(1);
210 }
211
212
213 void VISU::CutLines_i::SetDisplacement(CORBA::Double theDisp) { 
214   myCutLinesPL->SetDisplacement(theDisp);
215 }
216 void VISU::CutLines_i::SetDisplacement2(CORBA::Double theDisp) { 
217   myCutLinesPL->SetDisplacement(theDisp,1);
218 }
219
220 CORBA::Double VISU::CutLines_i::GetDisplacement() { 
221   return myCutLinesPL->GetDisplacement();
222 }
223 CORBA::Double VISU::CutLines_i::GetDisplacement2() { 
224   return myCutLinesPL->GetDisplacement(1);
225 }
226
227
228 void VISU::CutLines_i::SetBasePlanePosition(CORBA::Double thePlanePosition){
229   myCutLinesPL->SetPosition(thePlanePosition);
230 }
231
232 CORBA::Double VISU::CutLines_i::GetBasePlanePosition(){ 
233   return myCutLinesPL->GetPosition();
234 }
235
236 void VISU::CutLines_i::SetLinePosition(CORBA::Long thePlaneNumber, CORBA::Double thePlanePosition){
237   myCutLinesPL->SetPartPosition(thePlaneNumber,thePlanePosition);
238 }
239
240 CORBA::Double VISU::CutLines_i::GetLinePosition(CORBA::Long thePlaneNumber){ 
241   return myCutLinesPL->GetPartPosition(thePlaneNumber,1);
242 }
243
244
245 void VISU::CutLines_i::SetDefault(){
246   myCutLinesPL->SetDefault();
247 }
248
249 CORBA::Boolean VISU::CutLines_i::IsDefault(){ 
250   return myCutLinesPL->IsDefault();
251 }
252
253 void VISU::CutLines_i::SetDefaultPosition(CORBA::Long thePlaneNumber){
254   myCutLinesPL->SetPartDefault(thePlaneNumber);
255 }
256
257 CORBA::Boolean VISU::CutLines_i::IsDefaultPosition(CORBA::Long thePlaneNumber){ 
258   return myCutLinesPL->IsPartDefault(thePlaneNumber);
259 }
260
261 /*! Invert all curves of corresponding table
262  * see void VISU::CutLines_i::SetCurveInverted(CORBA::Long theCurveNumber,CORBA::Boolean theInvert)
263  * \param theInvert - Invert all curves, if value is TRUE, else not.
264  */
265 void VISU::CutLines_i::SetAllCurvesInverted(CORBA::Boolean theInvert){
266   for (int i=0; i<GetNbLines(); i++) SetCurveInverted(i,theInvert);
267 }
268
269 /*! Checks the orientation of all curves
270  * \retval TRUE - if all curves are inverted, else FALSE
271  */
272 CORBA::Boolean VISU::CutLines_i::IsAllCurvesInverted(){
273   for (int i=0; i<GetNbLines(); i++)
274     if (!IsCurveInverted(i)) return false;
275   return true;
276 }
277
278 /*! Sets orientation of curve
279  * \param theCurveNumber - integer value, number of cut line.
280  * \param theInvert      - boolean value, TRUE or false.
281  */
282 void VISU::CutLines_i::SetCurveInverted(CORBA::Long theCurveNumber,CORBA::Boolean theInvert){
283   myMapCurvesInverted[theCurveNumber] = theInvert;
284 }
285
286 /*! Checks orientation of curve.
287  * \param theCurveNumber - integer value, number of cut line.
288  * \retval TRUE - if line in the table is inverted, else FALSE.
289  */
290 CORBA::Boolean VISU::CutLines_i::IsCurveInverted(CORBA::Long theCurveNumber){
291   return myMapCurvesInverted[theCurveNumber];
292 }
293
294 void VISU::CutLines_i::SetNbLines(CORBA::Long theNb) { 
295   myCutLinesPL->SetNbParts(theNb);
296 }
297 CORBA::Long VISU::CutLines_i::GetNbLines() { 
298   return myCutLinesPL->GetNbParts();
299 }
300
301
302 void VISU::CutLines_i::DoHook(){
303   if(!myPipeLine) myPipeLine = VISU_CutLinesPL::New();
304   myCutLinesPL = dynamic_cast<VISU_CutLinesPL*>(myPipeLine);
305
306   ScalarMap_i::DoHook();
307 }
308
309 void VISU::CutLines_i::BuildTableOfReal(SALOMEDS::SObject_ptr theSObject){
310   try{
311     if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal");
312     Update();
313     SALOMEDS::GenericAttribute_var anAttr;
314     SALOMEDS::StudyBuilder_var aStudyBuilder = myStudy->NewBuilder();
315     anAttr = aStudyBuilder->FindOrCreateAttribute(theSObject, "AttributeTableOfReal");
316     SALOMEDS::AttributeTableOfReal_var aTableOfReal = SALOMEDS::AttributeTableOfReal::_narrow(anAttr);
317     
318     typedef set<float> TXCont;
319     typedef map<float,float> TXYMap;
320     typedef map<int,TXYMap> TXYMapCont;
321     typedef map<long,long> TLineIdCont;
322     
323     QString aTitle;
324     aTitle.sprintf("%s",myTitle.c_str());
325     aTitle = aTitle.simplifyWhiteSpace();
326     aTableOfReal->SetTitle(aTitle.latin1());
327     
328     int iLineEnd = myCutLinesPL->GetAppendPolyData()->GetNumberOfInputs();
329     if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal iLineEnd = "<<iLineEnd);
330     TXCont aXCont;
331     TXYMapCont aXYMapCont; 
332     TLineIdCont aLineIdCont;  // Define internal numeration of lines
333     const float *aDirLn = myCutLinesPL->GetDirLn();
334     const float *aBasePnt = myCutLinesPL->GetBasePnt();
335     const float *aBoundPrjLn = myCutLinesPL->GetBoundPrjLn();
336     for(int iLine = 0, jLine = 0; iLine < iLineEnd; iLine++){
337       vtkDataSet *aDataSet = myCutLinesPL->GetAppendPolyData()->GetInput(iLine);
338       aDataSet->Update();
339       int aNbPoints = aDataSet->GetNumberOfPoints();
340       if(!aNbPoints) continue;
341       vtkPointData *aPointData = aDataSet->GetPointData();
342       vtkDataArray *aScalars = aPointData->GetScalars();
343       vtkCellDataToPointData *aFilter = NULL;
344       if(!aScalars) {
345         aFilter = vtkCellDataToPointData::New();
346         aFilter->SetInput(aDataSet);
347         aFilter->PassCellDataOn();
348         aDataSet = aFilter->GetOutput();
349         aDataSet->Update();
350       }
351       aPointData = aDataSet->GetPointData();
352       aScalars = aPointData->GetScalars();
353       if(!aScalars) continue;
354       if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal iLine = "<<iLine<<"; aNbPoints = "<<aNbPoints);
355       aLineIdCont[iLine] = jLine++;
356       TXYMap& aXYMap = aXYMapCont[iLine];
357       float aPnt[3], aVect[3], aDist;
358       for(int i = 0; i < aNbPoints; i++){
359         aDataSet->GetPoint(i,aPnt);
360         Sub(aPnt,aBasePnt,aVect);
361         if ( fabs(aBoundPrjLn[2]) < EPS_machine )
362           aDist = 0.5;
363         else
364           {
365             aDist = vtkMath::Dot(aVect,aDirLn) / aBoundPrjLn[2];
366             // the workaround
367             if(aDist < 0.0) aDist = 0.0; 
368             if(aDist > 1.0) aDist = 1.0;
369           }
370         aXYMap[aDist] = aScalars->GetTuple1(i);
371       }
372       if(aFilter){
373         aFilter->UnRegisterAllOutputs();
374         aFilter->Delete();
375       }
376     }
377     if(aXYMapCont.size() == 0)
378       throw std::runtime_error("CutPlanes_i::BuildTableOfReal aXYMapCont.size() == 0 !!!");
379
380     {
381       // Invertion all curves in the table, which has inversion flag is TRUE (see \a myMapCurvesInverted)
382       for(int iLine=0; iLine < iLineEnd; iLine++){
383         if (!IsCurveInverted(iLine)) continue;
384         TXYMap aNewXYMap;
385         TXYMap& aXYMap = aXYMapCont[iLine];
386         TXYMap::const_iterator aXYMapIter = aXYMap.begin();
387         std::list<float> XKeys;
388         for (;aXYMapIter != aXYMap.end() ; aXYMapIter++) XKeys.push_back(aXYMapIter->first);
389         XKeys.sort();
390         if (XKeys.size() > 1) {
391           float a_first_indx = XKeys.front();
392           float a_last_indx = XKeys.back();
393           if (a_first_indx > a_last_indx){
394             XKeys.reverse();
395             float tmp = a_first_indx;
396             a_first_indx = a_last_indx;
397             a_last_indx = tmp;
398           }
399           std::list<float>::const_iterator aIter = XKeys.begin();
400           for (int k=0;k<XKeys.size() and aIter != XKeys.end();k++,aIter++){
401             // Warning: value '1.0' come from workaround:
402             // see also aDist = vtkMath::Dot(aVect,aDirLn) / aBoundPrjLn[2];
403             // aDist >= 0 and aDist<=1.0
404             aNewXYMap[1.0 - *aIter] = aXYMap[*aIter];
405           }
406           TXYMap::const_iterator aNewXYMapIter = aNewXYMap.begin();
407           aXYMap.clear();
408           for (;aNewXYMapIter != aNewXYMap.end();aNewXYMapIter++) {
409             aXYMap[aNewXYMapIter->first] = aNewXYMapIter->second;
410           }
411         }
412       }
413     }
414     //Resorting of theXYMap
415     TXYMapCont::iterator aXYMapContIter = aXYMapCont.begin();
416     for(; aXYMapContIter != aXYMapCont.end(); aXYMapContIter++){
417       TXYMap& aXYMap = aXYMapContIter->second, aNewXYMap;
418       if(aXYMap.size() > 2){  
419         // Try to smooth the values of the line by applying linear approximation
420         TXYMap::const_iterator aXYMapIter[2] = {aXYMap.begin(), ++aXYMap.begin()};
421         aNewXYMap[aXYMapIter[0]->first] = aXYMapIter[0]->second;
422         aXCont.insert(aXYMapIter[0]->first);
423         for(; aXYMapIter[1] != aXYMap.end(); aXYMapIter[0]++, aXYMapIter[1]++){
424           float aY[3] = {aXYMapIter[0]->second, aXYMapIter[1]->second, 0.0};
425           aY[2] = (aY[0] + aY[1])/2.0;
426           float aX[3] = {aXYMapIter[0]->first, aXYMapIter[1]->first, 0.0};
427           aX[2] = (aX[0] + aX[1])/2.0;
428           aNewXYMap[aX[2]] = aY[2];
429           aXCont.insert(aX[2]);
430         }
431         aNewXYMap[aXYMapIter[0]->first] = aXYMapIter[0]->second;
432         aXCont.insert(aXYMapIter[0]->first);
433         aXYMap = aNewXYMap;
434       }else{
435         TXYMap::const_iterator aXYMapIter = aXYMap.begin();
436         for(; aXYMapIter != aXYMap.end(); aXYMapIter++)
437           aXCont.insert(aXYMapIter->first);
438       }
439     }
440     if(aXCont.size() == 0)
441       throw std::runtime_error("CutPlanes_i::BuildTableOfReal aXCont.size() == 0 !!!");
442     QString aString;
443     int iEnd = aXCont.size();
444     aTableOfReal->SetNbColumns(iEnd);
445     TXCont::const_iterator aXContIter = aXCont.begin();
446     for(long i = 0; aXContIter != aXCont.end(); aXContIter++, i++){
447       float aDist = *aXContIter; 
448       aTableOfReal->PutValue(aDist,1,i+1);
449       aString.sprintf("%d",i);
450       aTableOfReal->SetColumnTitle(i+1,aString.latin1());
451       if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal aDist = "<<aDist);
452       TXYMapCont::const_iterator aXYMapContIter = aXYMapCont.begin();
453       for(; aXYMapContIter != aXYMapCont.end(); aXYMapContIter++){
454         long iLine = aXYMapContIter->first;
455         long iLineId = aLineIdCont[iLine];
456         const TXYMap& aXYMap = aXYMapCont[iLine];
457         TXYMap::const_iterator aXYMapIter = aXYMap.find(aDist);
458         // Can we find some value that belong to the line and have the same X coordinate?
459         if(aXYMapIter == aXYMap.end()) continue;
460         float aVal = aXYMapIter->second;
461         aTableOfReal->PutValue(aVal,iLineId+2,i+1);
462       }
463     }
464     {
465       aTableOfReal->SetRowTitle(1,"X");
466       aTableOfReal->SetRowUnit(1,"-");
467       QString aUnitName = myField->myUnitNames[0].c_str();
468       int aScalarMode = myCutLinesPL->GetScalarMode();
469       if(aScalarMode != 0) 
470         aUnitName = myField->myUnitNames[aScalarMode-1].c_str();
471       aUnitName = aUnitName.simplifyWhiteSpace();
472       if(aUnitName.isEmpty()) aUnitName = "-";
473       TXYMapCont::const_iterator aXYMapContIter = aXYMapCont.begin();
474       for(; aXYMapContIter != aXYMapCont.end(); aXYMapContIter++){
475         long iLine = aXYMapContIter->first;
476         long iLineId = aLineIdCont[iLine];
477         aString.sprintf("Y%d",iLine);
478         if(MYDEBUG) 
479           MESSAGE("CutPlanes_i::BuildTableOfReal - SetRowTitle("<<iLineId+2<<",'"<<aString<<"')");
480         aTableOfReal->SetRowTitle(iLineId+2,aString.latin1());
481         aTableOfReal->SetRowUnit(iLineId+2,aUnitName.latin1());
482       }
483     }
484   }catch(std::exception& exc){
485     INFOS("Follow exception was occured :\n"<<exc.what());
486   }catch (...){
487     INFOS("Unknown exception was occured !!!");
488   }
489 }