1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : VISU_CutLinesBase_i.cc
21 // Author : Oleg UVAROV
24 #include "VISU_CutLinesBase_i.hh"
25 #include "VISU_Prs3dUtils.hh"
26 #include "VISU_Result_i.hh"
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"
34 #include "SUIT_ResourceMgr.h"
36 #include <vtkAppendPolyData.h>
38 static vtkFloatingPointType EPS_machine = 1.0E-7;
41 static int MYDEBUG = 0;
43 static int MYDEBUG = 0;
48 //---------------------------------------------------------------
49 VISU::CutLinesBase_i::
50 CutLinesBase_i(EPublishInStudyMode thePublishInStudyMode) :
51 ColoredPrs3d_i(thePublishInStudyMode),
52 ScalarMap_i(thePublishInStudyMode),
53 myUseAbsLength( false ),
54 myCutLinesBasePL(NULL)
58 //---------------------------------------------------------------
61 ::SameAs(const Prs3d_i* theOrigin)
63 TSuperClass::SameAs(theOrigin);
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());
73 //---------------------------------------------------------------
74 /*! Copy map to /a myMapCurvesInverted.
75 * \param theCurves - map
79 ::CopyCurvesInverted(const TCurvesInv& theCurves)
81 myMapCurvesInverted = theCurves;
85 //---------------------------------------------------------------
88 ::Create(const std::string& theMeshName,
89 VISU::Entity theEntity,
90 const std::string& theFieldName,
91 CORBA::Long theTimeStampNumber)
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);
100 //---------------------------------------------------------------
103 ::Restore(SALOMEDS::SObject_ptr theSObject,
104 const Storable::TRestoringMap& theMap)
106 if(!TSuperClass::Restore(theSObject, theMap))
109 SetNbLines(VISU::Storable::FindValue(theMap,"myNbLines").toInt());
111 SetUseAbsoluteLength(VISU::Storable::FindValue(theMap,"myUseAbsLength").toInt());
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);
120 SetCurveInverted(i,false);
123 for(int i = 0, iEnd = GetNbLines(); i < iEnd ; i++)
124 SetCurveInverted(i,false);
131 //---------------------------------------------------------------
134 ::ToStream(std::ostringstream& theStr)
136 TSuperClass::ToStream(theStr);
138 Storable::DataToStream( theStr, "myNbLines", GetNbLines() );
140 Storable::DataToStream( theStr, "myUseAbsLength", IsUseAbsoluteLength());
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());
150 //---------------------------------------------------------------
154 if(MYDEBUG) MESSAGE("CutLinesBase_i::~CutLinesBase_i()");
158 //----------------------------------------------------------------------------^
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);
174 //---------------------------------------------------------------
177 ::SetNbLines(CORBA::Long theNb)
179 VISU::TSetModified aModified(this);
181 ProcessVoidEvent(new TVoidMemFun1ArgEvent<VISU_CutLinesBasePL, int>
182 (GetSpecificPL(), &VISU_CutLinesBasePL::SetNbParts, theNb));
185 //---------------------------------------------------------------
190 return myCutLinesBasePL->GetNbParts();
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.
200 ::SetAllCurvesInverted(CORBA::Boolean theInvert)
202 for(int i=0; i < GetNbLines(); i++)
203 SetCurveInverted(i, theInvert);
206 //---------------------------------------------------------------
207 /*! Checks the orientation of all curves
208 * \retval TRUE - if all curves are inverted, else FALSE
212 ::IsAllCurvesInverted()
214 for (int i=0; i<GetNbLines(); i++)
215 if (!IsCurveInverted(i)) return false;
219 //---------------------------------------------------------------
220 /*! Sets orientation of curve
221 * \param theCurveNumber - integer value, number of cut line.
222 * \param theInvert - boolean value, TRUE or false.
226 ::SetCurveInverted(CORBA::Long theCurveNumber, CORBA::Boolean theInvert)
228 if(myMapCurvesInverted[theCurveNumber] == theInvert)
231 VISU::TSetModified aModified(this);
233 myMapCurvesInverted[theCurveNumber] = theInvert;
234 myParamsTime.Modified();
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.
244 ::IsCurveInverted(CORBA::Long theCurveNumber)
246 return myMapCurvesInverted[theCurveNumber];
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.
255 ::SetUseAbsoluteLength(CORBA::Boolean theAbsLength)
257 if ( myUseAbsLength == theAbsLength )
260 VISU::TSetModified aModified(this);
262 myUseAbsLength = theAbsLength;
263 myParamsTime.Modified();
266 //---------------------------------------------------------------
269 ::IsUseAbsoluteLength()
271 return myUseAbsLength;
275 //---------------------------------------------------------------
278 ::CreatePipeLine(VISU_PipeLine* thePipeLine)
280 // temporarily commented (see note 0006576 of the external issue 0020468)
281 //myCutLinesBasePL = dynamic_cast<VISU_CutLinesBasePL*>(thePipeLine);
282 myCutLinesBasePL = (VISU_CutLinesBasePL*)thePipeLine;
284 TSuperClass::CreatePipeLine(myCutLinesBasePL);
288 //---------------------------------------------------------------
291 ::BuildTableOfReal(SALOMEDS::SObject_var theSObject, bool theIsCutSegment)
294 if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal");
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);
301 typedef set<vtkFloatingPointType> TXCont;
302 typedef map<vtkFloatingPointType,vtkFloatingPointType> TXYMap;
303 typedef map<int,TXYMap> TXYMapCont;
304 typedef map<long,long> TLineIdCont;
306 QString aTitle( GetScalarBarTitle().c_str() );
307 aTitle = aTitle.simplified();
308 aTableOfReal->SetTitle( aTitle.toLatin1().data() );
310 int iLineEnd = myCutLinesBasePL->GetAppendPolyData()->GetNumberOfInputConnections(0);
311 if(MYDEBUG) MESSAGE("CutPlanes_i::BuildTableOfReal iLineEnd = "<<iLineEnd);
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);
321 int aNbPoints = aDataSet->GetNumberOfPoints();
322 if(!aNbPoints) continue;
323 vtkPointData *aPointData = aDataSet->GetPointData();
324 vtkDataArray *aScalars = aPointData->GetScalars();
325 VISU_CellDataToPointData *aFilter = NULL;
327 aFilter = VISU_CellDataToPointData::New();
328 aFilter->SetInput(aDataSet);
329 aFilter->PassCellDataOn();
330 aDataSet = aFilter->GetOutput();
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() ){
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 )
356 aDist = vtkMath::Dot(aVect,aDirLn)/aDivide;
358 if(aDist < 0.0) aDist = 0.0;
359 if(aDist > aTopBnd) aDist = aTopBnd;
361 aXYMap[aDist] = aScalars->GetTuple1(i);
366 if(aXYMapCont.size() == 0)
367 throw std::runtime_error("CutPlanes_i::BuildTableOfReal aXYMapCont.size() == 0 !!!");
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;
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);
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){
384 vtkFloatingPointType tmp = a_first_indx;
385 a_first_indx = a_last_indx;
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() ){
397 aNewXYMap[aTopBnd - *aIter] = aXYMap[*aIter];
399 TXYMap::const_iterator aNewXYMapIter = aNewXYMap.begin();
401 for (;aNewXYMapIter != aNewXYMap.end();aNewXYMapIter++) {
402 aXYMap[aNewXYMapIter->first] = aNewXYMapIter->second;
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]);
424 aNewXYMap[aXYMapIter[0]->first] = aXYMapIter[0]->second;
425 aXCont.insert(aXYMapIter[0]->first);
428 TXYMap::const_iterator aXYMapIter = aXYMap.begin();
429 for(; aXYMapIter != aXYMap.end(); aXYMapIter++)
430 aXCont.insert(aXYMapIter->first);
433 if(aXCont.size() == 0)
434 throw std::runtime_error("CutPlanes_i::BuildTableOfReal aXCont.size() == 0 !!!");
436 int iEnd = aXCont.size();
437 aTableOfReal->SetNbColumns(iEnd);
438 TXCont::const_iterator aXContIter = aXCont.begin();
439 vtkFloatingPointType aMinDist = *aXContIter;
440 aXContIter = aXCont.end();
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;
451 if(!IsUseAbsoluteLength() && fabs(aMaxDist - aMinDist) > EPS_machine)
452 aXVal /= (aMaxDist - aMinDist);
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);
471 aTableOfReal->SetRowTitle(1,"X");
472 aTableOfReal->SetRowUnit(1,"-");
473 QString aUnitName = GetField()->myUnitNames[0].c_str();
474 int aScalarMode = myCutLinesBasePL->GetScalarMode();
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);
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());
490 }catch(std::exception& exc){
491 INFOS("Follow exception was occured :\n"<<exc.what());
493 INFOS("Unknown exception was occured !!!");