Salome HOME
2bcfe955acda9716ae459a7d74d4016457d8ba0f
[modules/visu.git] / src / VISU_I / VISU_CutLinesBase_i.cc
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  File   : VISU_CutLinesBase_i.cc
21 //  Author : Oleg UVAROV
22 //  Module : VISU
23 //
24 #include "VISU_CutLinesBase_i.hh"
25 #include "VISU_Prs3dUtils.hh"
26 #include "VISU_Result_i.hh"
27
28 #include "VISU_Actor.h"
29 #include "VISU_ScalarMapAct.h"
30 #include "VISU_CutLinesBasePL.hxx"
31 #include "VISU_Convertor.hxx"
32 #include "VISU_PipeLineUtils.hxx"
33
34 #include "SUIT_ResourceMgr.h"
35
36 #include <vtkAppendPolyData.h>
37
38 static vtkFloatingPointType EPS_machine = 1.0E-7;
39
40 #ifdef _DEBUG_
41 static int MYDEBUG = 0;
42 #else
43 static int MYDEBUG = 0;
44 #endif
45
46 using namespace std;
47
48 //---------------------------------------------------------------
49 VISU::CutLinesBase_i::
50 CutLinesBase_i(EPublishInStudyMode thePublishInStudyMode) :
51   ColoredPrs3d_i(thePublishInStudyMode),
52   ScalarMap_i(thePublishInStudyMode),
53   myUseAbsLength( false ),
54   myCutLinesBasePL(NULL)
55 {}
56
57
58 //---------------------------------------------------------------
59 void
60 VISU::CutLinesBase_i
61 ::SameAs(const Prs3d_i* theOrigin)
62 {
63   TSuperClass::SameAs(theOrigin);
64
65   if(const CutLinesBase_i* aPrs3d = dynamic_cast<const CutLinesBase_i*>(theOrigin)){
66     CutLinesBase_i* anOrigin = const_cast<CutLinesBase_i*>(aPrs3d);
67     myUseAbsLength = anOrigin->IsUseAbsoluteLength();
68     CopyCurvesInverted(anOrigin->GetCurvesInverted());
69   }
70 }
71
72
73 //---------------------------------------------------------------
74 /*! Copy map to /a myMapCurvesInverted.
75  * \param theCurves - map
76  */
77 void 
78 VISU::CutLinesBase_i
79 ::CopyCurvesInverted(const TCurvesInv& theCurves)
80 {
81   myMapCurvesInverted = theCurves;
82 }
83
84
85 //---------------------------------------------------------------
86 VISU::Storable* 
87 VISU::CutLinesBase_i
88 ::Create(const std::string& theMeshName, 
89          VISU::Entity theEntity,
90          const std::string& theFieldName, 
91          CORBA::Long theTimeStampNumber)
92 {
93   SUIT_ResourceMgr* aResourceMgr = VISU::GetResourceMgr();
94   SetUseAbsoluteLength( aResourceMgr->booleanValue( "VISU", "use_absolute_length", false ) );
95   SetAllCurvesInverted( aResourceMgr->booleanValue( "VISU", "invert_all_curves", false ) );
96   return TSuperClass::Create(theMeshName,theEntity,theFieldName,theTimeStampNumber);
97 }
98
99
100 //---------------------------------------------------------------
101 VISU::Storable* 
102 VISU::CutLinesBase_i
103 ::Restore(SALOMEDS::SObject_ptr theSObject,
104           const Storable::TRestoringMap& theMap)
105 {
106   if(!TSuperClass::Restore(theSObject, theMap))
107     return NULL;
108
109   SetNbLines(VISU::Storable::FindValue(theMap,"myNbLines").toInt());
110
111   SetUseAbsoluteLength(VISU::Storable::FindValue(theMap,"myUseAbsLength").toInt());
112
113   // Restoring the map - \a myMapCurvesInverted
114   QStringList aMapCurvesInverted = VISU::Storable::FindValue(theMap,"myMapCurvesInverted").split("|",QString::SkipEmptyParts );
115   if (aMapCurvesInverted.count() == GetNbLines()){
116     for(int i = 0, iEnd = GetNbLines(); i < iEnd ; i++){
117       if(aMapCurvesInverted[i].toInt())
118         SetCurveInverted(i,true);
119       else
120         SetCurveInverted(i,false);
121     }
122   } else {
123     for(int i = 0, iEnd = GetNbLines(); i < iEnd ; i++)
124       SetCurveInverted(i,false);
125   }
126       
127   return this;
128 }
129
130
131 //---------------------------------------------------------------
132 void
133 VISU::CutLinesBase_i
134 ::ToStream(std::ostringstream& theStr)
135 {
136   TSuperClass::ToStream(theStr);
137
138   Storable::DataToStream( theStr, "myNbLines",      GetNbLines() );
139
140   Storable::DataToStream( theStr, "myUseAbsLength", IsUseAbsoluteLength());
141
142   // Storing the map - \a myMapCurvesInverted
143   QString aStrCurvesInverted;
144   for(int i = 0, iEnd = GetNbLines(); i < iEnd; i++) 
145     aStrCurvesInverted.append(QString::number(IsCurveInverted(i)) + "|");
146   Storable::DataToStream( theStr, "myMapCurvesInverted", (const char*)aStrCurvesInverted.toLatin1());
147 }
148
149
150 //---------------------------------------------------------------
151 VISU::CutLinesBase_i
152 ::~CutLinesBase_i()
153 {
154   if(MYDEBUG) MESSAGE("CutLinesBase_i::~CutLinesBase_i()");
155 }
156
157
158 //----------------------------------------------------------------------------^
159 VISU_Actor*
160 VISU::CutLinesBase_i
161 ::CreateActor()
162 {
163   VISU_Actor* anActor = TSuperClass::CreateActor();
164   if(VISU_ScalarMapAct* aScalarMapAct = dynamic_cast<VISU_ScalarMapAct*>(anActor)) {
165     //rnv: To fix the bug IPAL22007 Cut Lines in VTK viewer are shown with square points on ends
166     //rnv: set small size of the vertices for the "Cut Lines" and "Cut Segment" presentations.
167     aScalarMapAct->Set0DElemSize(1.0);
168   }
169   return anActor;
170 }
171
172
173
174 //---------------------------------------------------------------
175 void
176 VISU::CutLinesBase_i
177 ::SetNbLines(CORBA::Long theNb) 
178
179   VISU::TSetModified aModified(this);
180
181   ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_CutLinesBasePL, int>
182                    (GetSpecificPL(), &VISU_CutLinesBasePL::SetNbParts, theNb));
183 }
184
185 //---------------------------------------------------------------
186 CORBA::Long
187 VISU::CutLinesBase_i
188 ::GetNbLines() 
189
190   return myCutLinesBasePL->GetNbParts();
191 }
192
193 //---------------------------------------------------------------
194 /*! Invert all curves of corresponding table
195  * see void VISU::CutLinesBase_i::SetCurveInverted(CORBA::Long theCurveNumber,CORBA::Boolean theInvert)
196  * \param theInvert - Invert all curves, if value is TRUE, else not.
197  */
198 void
199 VISU::CutLinesBase_i
200 ::SetAllCurvesInverted(CORBA::Boolean theInvert)
201 {
202   for(int i=0; i < GetNbLines(); i++)
203     SetCurveInverted(i, theInvert);
204 }
205
206 //---------------------------------------------------------------
207 /*! Checks the orientation of all curves
208  * \retval TRUE - if all curves are inverted, else FALSE
209  */
210 CORBA::Boolean 
211 VISU::CutLinesBase_i
212 ::IsAllCurvesInverted()
213 {
214   for (int i=0; i<GetNbLines(); i++)
215     if (!IsCurveInverted(i)) return false;
216   return true;
217 }
218
219 //---------------------------------------------------------------
220 /*! Sets orientation of curve
221  * \param theCurveNumber - integer value, number of cut line.
222  * \param theInvert      - boolean value, TRUE or false.
223  */
224 void
225 VISU::CutLinesBase_i
226 ::SetCurveInverted(CORBA::Long theCurveNumber, CORBA::Boolean theInvert)
227 {
228   if(myMapCurvesInverted[theCurveNumber] == theInvert)
229     return;
230
231   VISU::TSetModified aModified(this);
232
233   myMapCurvesInverted[theCurveNumber] = theInvert;
234   myParamsTime.Modified();
235 }
236
237 //---------------------------------------------------------------
238 /*! Checks orientation of curve.
239  * \param theCurveNumber - integer value, number of cut line.
240  * \retval TRUE - if line in the table is inverted, else FALSE.
241  */
242 CORBA::Boolean
243 VISU::CutLinesBase_i
244 ::IsCurveInverted(CORBA::Long theCurveNumber)
245 {
246   return myMapCurvesInverted[theCurveNumber];
247 }
248
249 //---------------------------------------------------------------
250 /*! It control the way the length of cutlines is shown: using aboslute or relative values
251 * \param theAbsLength - boolean value, TRUE or false.
252 */
253 void
254 VISU::CutLinesBase_i
255 ::SetUseAbsoluteLength(CORBA::Boolean theAbsLength)
256 {
257   if ( myUseAbsLength == theAbsLength )
258     return;
259
260   VISU::TSetModified aModified(this);
261
262   myUseAbsLength = theAbsLength;
263   myParamsTime.Modified();
264 }
265
266 //---------------------------------------------------------------
267 CORBA::Boolean
268 VISU::CutLinesBase_i
269 ::IsUseAbsoluteLength()
270 {
271   return myUseAbsLength;
272 }
273
274
275 //---------------------------------------------------------------
276 void
277 VISU::CutLinesBase_i
278 ::CreatePipeLine(VISU_PipeLine* thePipeLine)
279 {
280   // temporarily commented (see note 0006576 of the external issue 0020468)
281   //myCutLinesBasePL = dynamic_cast<VISU_CutLinesBasePL*>(thePipeLine);
282   myCutLinesBasePL = (VISU_CutLinesBasePL*)thePipeLine;
283
284   TSuperClass::CreatePipeLine(myCutLinesBasePL);
285 }
286
287
288 //---------------------------------------------------------------
289 void
290 VISU::CutLinesBase_i
291 ::BuildTableOfReal(SALOMEDS::SObject_var theSObject, bool theIsCutSegment)
292 {
293   try{
294     if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal");
295     Update();
296     SALOMEDS::GenericAttribute_var anAttr;
297     SALOMEDS::StudyBuilder_var aStudyBuilder = GetStudyDocument()->NewBuilder();
298     anAttr = aStudyBuilder->FindOrCreateAttribute(theSObject, "AttributeTableOfReal");
299     SALOMEDS::AttributeTableOfReal_var aTableOfReal = SALOMEDS::AttributeTableOfReal::_narrow(anAttr);
300     
301     typedef set<vtkFloatingPointType> TXCont;
302     typedef map<vtkFloatingPointType,vtkFloatingPointType> TXYMap;
303     typedef map<int,TXYMap> TXYMapCont;
304     typedef map<long,long> TLineIdCont;
305     
306     QString aTitle( GetScalarBarTitle().c_str() );
307     aTitle = aTitle.simplified();
308     aTableOfReal->SetTitle( aTitle.toLatin1().data() );
309     
310     int iLineEnd = myCutLinesBasePL->GetAppendPolyData()->GetNumberOfInputConnections(0);
311     if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal iLineEnd = "<<iLineEnd);
312     TXCont aXCont;
313     TXYMapCont aXYMapCont; 
314     TLineIdCont aLineIdCont;  // Define internal numeration of lines
315     const vtkFloatingPointType *aDirLn = myCutLinesBasePL->GetDirLn();
316     const vtkFloatingPointType *aBasePnt = myCutLinesBasePL->GetBasePnt();
317     const vtkFloatingPointType *aBoundPrjLn = myCutLinesBasePL->GetBoundPrjLn();
318     for(int iLine = 0, jLine = 0; iLine < iLineEnd; iLine++){
319       vtkDataSet *aDataSet = myCutLinesBasePL->GetAppendPolyData()->GetInput(iLine);
320       aDataSet->Update();
321       int aNbPoints = aDataSet->GetNumberOfPoints();
322       if(!aNbPoints) continue;
323       vtkPointData *aPointData = aDataSet->GetPointData();
324       vtkDataArray *aScalars = aPointData->GetScalars();
325       VISU_CellDataToPointData *aFilter = NULL;
326       if(!aScalars) {
327         aFilter = VISU_CellDataToPointData::New();
328         aFilter->SetInput(aDataSet);
329         aFilter->PassCellDataOn();
330         aDataSet = aFilter->GetOutput();
331         aDataSet->Update();
332       }
333       aPointData = aDataSet->GetPointData();
334       aScalars = aPointData->GetScalars();
335       if(!aScalars) continue;
336       if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal iLine = "<<iLine<<"; aNbPoints = "<<aNbPoints);
337       aLineIdCont[iLine] = jLine++;
338       TXYMap& aXYMap = aXYMapCont[iLine];
339       vtkFloatingPointType aPnt[3], aVect[3], aDist, aTopBnd, aDivide;
340       aTopBnd = aBoundPrjLn[2];
341       aDivide = aBoundPrjLn[2];
342       if( !IsUseAbsoluteLength() ){
343         aTopBnd = 1.0;
344       }
345       else aDivide = 1.0;
346
347       for(int i = 0; i < aNbPoints; i++){
348         aDataSet->GetPoint(i,aPnt);
349         for(int j = 0; j < 3; j++)
350           aVect[j] = aPnt[j] - aBasePnt[j];
351         //VISU::Sub(aPnt,aBasePnt,aVect);
352         if ( fabs(aBoundPrjLn[2]) < EPS_machine )
353           aDist = 0.5;
354         else
355         {
356           aDist = vtkMath::Dot(aVect,aDirLn)/aDivide; 
357           // the workaround
358           if(aDist < 0.0) aDist = 0.0; 
359           if(aDist > aTopBnd) aDist = aTopBnd;
360         }
361         aXYMap[aDist] = aScalars->GetTuple1(i);
362       }
363       if(aFilter)
364         aFilter->Delete();
365     }
366     if(aXYMapCont.size() == 0)
367       throw std::runtime_error("CutPlanes_i::BuildTableOfReal aXYMapCont.size() == 0 !!!");
368
369     {
370       // Invertion all curves in the table, which has inversion flag is TRUE (see \a myMapCurvesInverted)
371       for(int iLine=0; iLine < iLineEnd; iLine++){
372         if (!IsCurveInverted(iLine)) continue;
373         TXYMap aNewXYMap;
374         TXYMap& aXYMap = aXYMapCont[iLine];
375         TXYMap::const_iterator aXYMapIter = aXYMap.begin();
376         std::list<vtkFloatingPointType> XKeys;
377         for (;aXYMapIter != aXYMap.end() ; aXYMapIter++) XKeys.push_back(aXYMapIter->first);
378         XKeys.sort();
379         if (XKeys.size() > 1) {
380           vtkFloatingPointType a_first_indx = XKeys.front();
381           vtkFloatingPointType a_last_indx = XKeys.back();
382           if (a_first_indx > a_last_indx){
383             XKeys.reverse();
384             vtkFloatingPointType tmp = a_first_indx;
385             a_first_indx = a_last_indx;
386             a_last_indx = tmp;
387           }
388           std::list<vtkFloatingPointType>::const_iterator aIter = XKeys.begin();
389           for (int k=0;k<XKeys.size() && aIter != XKeys.end();k++,aIter++){
390             // Warning: value '1.0' come from workaround:
391             // see also aDist = vtkMath::Dot(aVect,aDirLn) / aBoundPrjLn[2];
392             // aDist >= 0 and aDist<=1.0
393             vtkFloatingPointType aTopBnd = aBoundPrjLn[2];
394             if( !IsUseAbsoluteLength() ){
395               aTopBnd = 1.0;
396             }
397             aNewXYMap[aTopBnd - *aIter] = aXYMap[*aIter];
398           }
399           TXYMap::const_iterator aNewXYMapIter = aNewXYMap.begin();
400           aXYMap.clear();
401           for (;aNewXYMapIter != aNewXYMap.end();aNewXYMapIter++) {
402             aXYMap[aNewXYMapIter->first] = aNewXYMapIter->second;
403           }
404         }
405       }
406     }
407     //Resorting of theXYMap
408     TXYMapCont::iterator aXYMapContIter = aXYMapCont.begin();
409     for(; aXYMapContIter != aXYMapCont.end(); aXYMapContIter++){
410       TXYMap& aXYMap = aXYMapContIter->second, aNewXYMap;
411       if(aXYMap.size() > 2){  
412         // Try to smooth the values of the line by applying linear approximation
413         TXYMap::const_iterator aXYMapIter[2] = {aXYMap.begin(), ++aXYMap.begin()};
414         aNewXYMap[aXYMapIter[0]->first] = aXYMapIter[0]->second;
415         aXCont.insert(aXYMapIter[0]->first);
416         for(; aXYMapIter[1] != aXYMap.end(); aXYMapIter[0]++, aXYMapIter[1]++){
417           vtkFloatingPointType aY[3] = {aXYMapIter[0]->second, aXYMapIter[1]->second, 0.0};
418           aY[2] = (aY[0] + aY[1])/2.0;
419           vtkFloatingPointType aX[3] = {aXYMapIter[0]->first, aXYMapIter[1]->first, 0.0};
420           aX[2] = (aX[0] + aX[1])/2.0;
421           aNewXYMap[aX[2]] = aY[2];
422           aXCont.insert(aX[2]);
423         }
424         aNewXYMap[aXYMapIter[0]->first] = aXYMapIter[0]->second;
425         aXCont.insert(aXYMapIter[0]->first);
426         aXYMap = aNewXYMap;
427       }else{
428         TXYMap::const_iterator aXYMapIter = aXYMap.begin();
429         for(; aXYMapIter != aXYMap.end(); aXYMapIter++)
430           aXCont.insert(aXYMapIter->first);
431       }
432     }
433     if(aXCont.size() == 0)
434       throw std::runtime_error("CutPlanes_i::BuildTableOfReal aXCont.size() == 0 !!!");
435     QString aString;
436     int iEnd = aXCont.size();
437     aTableOfReal->SetNbColumns(iEnd);
438     TXCont::const_iterator aXContIter = aXCont.begin();
439     vtkFloatingPointType aMinDist = *aXContIter;
440     aXContIter = aXCont.end();
441     aXContIter--;
442     vtkFloatingPointType aMaxDist = *aXContIter;
443     if(aMaxDist < aMinDist)
444       throw std::runtime_error("CutPlanes_i::BuildTableOfReal aMaxDist < aMinDist !!!");
445     aXContIter = aXCont.begin();
446     for(long i = 0; aXContIter != aXCont.end(); aXContIter++, i++){
447       vtkFloatingPointType aDist = *aXContIter; 
448       vtkFloatingPointType aXVal = aDist;
449       if(theIsCutSegment){
450         aXVal -= aMinDist;
451         if(!IsUseAbsoluteLength() && fabs(aMaxDist - aMinDist) > EPS_machine)
452           aXVal /= (aMaxDist - aMinDist);
453       }
454       aTableOfReal->PutValue(aXVal,1,i+1);
455       aString.sprintf("%d",i);
456       aTableOfReal->SetColumnTitle(i+1,(const char*)aString.toLatin1());
457       if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal aDist = "<<aDist<<" aXVal = "<<aXVal);
458       TXYMapCont::const_iterator aXYMapContIter = aXYMapCont.begin();
459       for(; aXYMapContIter != aXYMapCont.end(); aXYMapContIter++){
460         long iLine = aXYMapContIter->first;
461         long iLineId = aLineIdCont[iLine];
462         const TXYMap& aXYMap = aXYMapCont[iLine];
463         TXYMap::const_iterator aXYMapIter = aXYMap.find(aDist);
464         // Can we find some value that belong to the line and have the same X coordinate?
465         if(aXYMapIter == aXYMap.end()) continue;
466         vtkFloatingPointType aVal = aXYMapIter->second;
467         aTableOfReal->PutValue(aVal,iLineId+2,i+1);
468       }
469     }
470     {
471       aTableOfReal->SetRowTitle(1,"X");
472       aTableOfReal->SetRowUnit(1,"-");
473       QString aUnitName = GetField()->myUnitNames[0].c_str();
474       int aScalarMode = myCutLinesBasePL->GetScalarMode();
475       if(aScalarMode != 0) 
476         aUnitName = GetField()->myUnitNames[aScalarMode-1].c_str();
477       aUnitName = aUnitName.simplified();
478       if(aUnitName.isEmpty()) aUnitName = "-";
479       TXYMapCont::const_iterator aXYMapContIter = aXYMapCont.begin();
480       for(; aXYMapContIter != aXYMapCont.end(); aXYMapContIter++){
481         long iLine = aXYMapContIter->first;
482         long iLineId = aLineIdCont[iLine];
483         aString.sprintf("Y%d",iLine);
484         if(MYDEBUG) 
485           MESSAGE("CutPlanes_i::BuildTableOfReal - SetRowTitle("<<iLineId+2<<",'"<<(const char*)aString.toLatin1()<<"')");
486         aTableOfReal->SetRowTitle(iLineId+2,(const char*)aString.toLatin1());
487         aTableOfReal->SetRowUnit(iLineId+2,(const char*)aUnitName.toLatin1());
488       }
489     }
490   }catch(std::exception& exc){
491     INFOS("Follow exception was occured :\n"<<exc.what());
492   }catch (...){
493     INFOS("Unknown exception was occured !!!");
494   }
495 }