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