Salome HOME
Implementation of the Point 2 of the 20948: EDF 1468 SMESH: Histogram of the quality...
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_VTKUtils.cxx
index 3841a194ec1b94575f6061bff163e0d4759c2a60..184eb903cb05f34e53a23b96a6d746761d2155fb 100644 (file)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -19,6 +19,7 @@
 //
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
+
 // SMESH SMESHGUI : GUI for SMESH component
 // File   : SMESHGUI_VTKUtils.cxx
 // Author : Open CASCADE S.A.S.
@@ -29,6 +30,7 @@
 #include "SMESHGUI.h"
 #include "SMESHGUI_Utils.h"
 #include "SMESHGUI_Filter.h"
+#include "SMESH_ControlsDef.hxx"
 
 #include <SMESH_Actor.h>
 #include <SMESH_ActorUtils.h>
 #include <SalomeApp_Application.h>
 #include <SalomeApp_Study.h>
 
+#ifndef DISABLE_PLOT2DVIEWER
+#include <SPlot2d_ViewModel.h>
+#include <SPlot2d_Histogram.h>
+#include <Plot2d_ViewManager.h>
+#endif
+
 // SALOME KERNEL includes
 #include <utilities.h>
 
@@ -64,6 +72,7 @@
 #include CORBA_CLIENT_HEADER(SMESH_Group)
 
 // VTK includes
+#include <vtkMath.h>
 #include <vtkRenderer.h>
 #include <vtkActorCollection.h>
 #include <vtkUnstructuredGrid.h>
@@ -120,7 +129,7 @@ namespace SMESH
       TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.find(aKey);
       if(anIter != VISUAL_OBJ_CONT.end()) {
         // for unknown reason, object destructor is not called, so clear object manually
-        anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
+        anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
         anIter->second->GetUnstructuredGrid()->SetPoints(0);
       }
       VISUAL_OBJ_CONT.erase(aKey);
@@ -162,7 +171,7 @@ namespace SMESH
     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
     for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
       // for unknown reason, object destructor is not called, so clear object manually
-      anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
+      anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
       anIter->second->GetUnstructuredGrid()->SetPoints(0);
     }
     VISUAL_OBJ_CONT.clear();
@@ -203,13 +212,16 @@ namespace SMESH
       }
     }
     TVisualObjCont::iterator anIter = VISUAL_OBJ_CONT.begin();
-    for ( ; anIter != VISUAL_OBJ_CONT.end(); ++anIter ) {
+    for ( ; anIter != VISUAL_OBJ_CONT.end(); ) {
       int curId = anIter->first.first;
       if ( curId == studyID ) {
         // for unknown reason, object destructor is not called, so clear object manually
-        anIter->second->GetUnstructuredGrid()->SetCells(0,0,0);
+        anIter->second->GetUnstructuredGrid()->SetCells(0,0,0,0,0);
         anIter->second->GetUnstructuredGrid()->SetPoints(0);
-        VISUAL_OBJ_CONT.erase( anIter-- );  // dercement occures before erase()
+        VISUAL_OBJ_CONT.erase( anIter++ ); // anIter++ returns a copy of self before incrementing
+      }
+      else {
+        anIter++;
       }
     }
   }
@@ -252,7 +264,7 @@ namespace SMESH
    */
   //================================================================================
 
-  TVisualObjPtr GetVisualObj(int theStudyId, const char* theEntry){
+  TVisualObjPtr GetVisualObj(int theStudyId, const char* theEntry, bool nulData){
     TVisualObjPtr aVisualObj;
     TVisualObjCont::key_type aKey(theStudyId,theEntry);
     try{
@@ -326,7 +338,11 @@ namespace SMESH
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
         OCC_CATCH_SIGNALS;
 #endif
-        objModified = aVisualObj->Update();
+        //MESSAGE("GetVisualObj");
+        if (nulData)
+                objModified = aVisualObj->NulData();
+        else
+          objModified = aVisualObj->Update();
       }
       catch (...) {
 #ifdef _DEBUG_
@@ -350,24 +366,24 @@ namespace SMESH
         MESSAGE ( "SMESHGUI_VTKUtils::GetVisualObj(), freeMB=" << freeMB
                << ", usedMB=" << usedMB );
 #endif
-        bool continu = false;
-        if ( usedMB * 10 > freeMB )
-          // even dont try to show
-          SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
-                                   QObject::tr("SMESH_NO_MESH_VISUALIZATION"));
-        else
-          // there is a chance to succeed
-          continu = SUIT_MessageBox::warning
-            (SMESHGUI::desktop(),
-             QObject::tr("SMESH_WRN_WARNING"),
-             QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
-             SUIT_MessageBox::Yes | SUIT_MessageBox::No, 
-             SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes;
-        if ( !continu ) {
-          // remove the corresponding actors from all views
-          RemoveVisualObjectWithActors( theEntry );
-          aVisualObj.reset();
-        }
+//        bool continu = false;
+//        if ( usedMB * 10 > freeMB )
+//          // even dont try to show
+//          SUIT_MessageBox::warning(SMESHGUI::desktop(), QObject::tr("SMESH_WRN_WARNING"),
+//                                   QObject::tr("SMESH_NO_MESH_VISUALIZATION"));
+//        else
+//          // there is a chance to succeed
+//          continu = SUIT_MessageBox::warning
+//            (SMESHGUI::desktop(),
+//             QObject::tr("SMESH_WRN_WARNING"),
+//             QObject::tr("SMESH_CONTINUE_MESH_VISUALIZATION"),
+//             SUIT_MessageBox::Yes | SUIT_MessageBox::No,
+//             SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes;
+//        if ( !continu ) {
+//          // remove the corresponding actors from all views
+//          RemoveVisualObjectWithActors( theEntry );
+//          aVisualObj.reset();
+//        }
       }
     }
 
@@ -594,11 +610,17 @@ namespace SMESH
             anActor->SetNodeColor( aColor.R, aColor.G, aColor.B );
           else if( aGroup->GetType() == SMESH::EDGE )
             anActor->SetEdgeColor( aColor.R, aColor.G, aColor.B );
+          else if( aGroup->GetType() == SMESH::ELEM0D )
+            anActor->Set0DColor( aColor.R, aColor.G, aColor.B );
           else
             anActor->SetSufaceColor( aColor.R, aColor.G, aColor.B );
         }
       }
     }
+    MESSAGE("CreateActor " << anActor);
+    if( anActor )
+      if( SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI() )
+        aSMESHGUI->addActorAsObserver( anActor );
     return anActor;
   }
 
@@ -609,6 +631,7 @@ namespace SMESH
 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
         OCC_CATCH_SIGNALS;
 #endif
+        MESSAGE("DisplayActor " << theActor);
         vtkWnd->AddActor(theActor);
         vtkWnd->Repaint();
       }
@@ -624,6 +647,7 @@ namespace SMESH
 
   void RemoveActor( SUIT_ViewWindow *theWnd, SMESH_Actor* theActor){
     if(SVTK_ViewWindow* vtkWnd = GetVtkViewWindow(theWnd)){
+        MESSAGE("RemoveActor " << theActor);
       vtkWnd->RemoveActor(theActor);
       if(theActor->hasIO()){
         Handle(SALOME_InteractiveObject) anIO = theActor->getIO();
@@ -635,6 +659,9 @@ namespace SMESH
           VISUAL_OBJ_CONT.erase(aKey);
         }
       }
+#ifndef DISABLE_PLOT2DVIEWER
+       ProcessIn2DViewers(theActor,RemoveFrom2dViewer);
+#endif
       theActor->Delete();
       vtkWnd->Repaint();
     }
@@ -662,6 +689,7 @@ namespace SMESH
 
   bool UpdateView(SUIT_ViewWindow *theWnd, EDisplaing theAction, const char* theEntry)
   {
+        //MESSAGE("UpdateView");
     bool OK = false;
     SVTK_ViewWindow* aViewWnd = GetVtkViewWindow(theWnd);
     if (!aViewWnd)
@@ -678,6 +706,7 @@ namespace SMESH
       case eDisplayAll: {
         while (vtkActor *anAct = aCollection->GetNextActor()) {
           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
+                MESSAGE("--- display " << anActor);
             anActor->SetVisibility(true);
           }
         }
@@ -685,8 +714,10 @@ namespace SMESH
       }
       case eDisplayOnly:
       case eEraseAll: {
+        //MESSAGE("---case eDisplayOnly");
         while (vtkActor *anAct = aCollection->GetNextActor()) {
           if (SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct)) {
+                //MESSAGE("--- erase " << anActor);
             anActor->SetVisibility(false);
           }
         }
@@ -696,10 +727,12 @@ namespace SMESH
           switch (theAction) {
             case eDisplay:
             case eDisplayOnly:
+                //MESSAGE("--- display " << anActor);
               anActor->SetVisibility(true);
               if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
               break;
             case eErase:
+                //MESSAGE("--- erase " << anActor);
               anActor->SetVisibility(false);
               break;
           }
@@ -708,11 +741,13 @@ namespace SMESH
           case eDisplay:
           case eDisplayOnly:
             {
+                //MESSAGE("---");
               SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(theWnd->getViewManager()->study());
               _PTR(Study) aDocument = aStudy->studyDS();
               // Pass non-visual objects (hypotheses, etc.), return true in this case
               CORBA::Long anId = aDocument->StudyId();
-              if (TVisualObjPtr aVisualObj = GetVisualObj(anId,theEntry))
+              TVisualObjPtr aVisualObj;
+              if ( (aVisualObj = GetVisualObj(anId,theEntry)) && aVisualObj->IsValid())
               {
                 if ((anActor = CreateActor(aDocument,theEntry,true))) {
                   bool needFitAll = noSmeshActors(theWnd); // fit for the first object only
@@ -735,6 +770,7 @@ namespace SMESH
 
 
   bool UpdateView(EDisplaing theAction, const char* theEntry){
+        //MESSAGE("UpdateView");
     SalomeApp_Study* aStudy = dynamic_cast< SalomeApp_Study* >( GetActiveStudy() );
     SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( aStudy->application() );
     SUIT_ViewWindow *aWnd = app->activeViewManager()->getActiveView();
@@ -773,6 +809,7 @@ namespace SMESH
 
   bool Update(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
   {
+        MESSAGE("Update");
     _PTR(Study) aStudy = GetActiveStudyDocument();
     CORBA::Long anId = aStudy->StudyId();
     if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry())) {
@@ -783,6 +820,18 @@ namespace SMESH
     return false;
   }
 
+  bool UpdateNulData(const Handle(SALOME_InteractiveObject)& theIO, bool theDisplay)
+  {
+        MESSAGE("UpdateNulData");
+    _PTR(Study) aStudy = GetActiveStudyDocument();
+    CORBA::Long anId = aStudy->StudyId();
+    if ( TVisualObjPtr aVisualObj = SMESH::GetVisualObj(anId,theIO->getEntry(), true)) {
+      if ( theDisplay )
+        UpdateView(SMESH::eDisplay,theIO->getEntry());
+      return true;
+    }
+    return false;
+  }
 
   void UpdateSelectionProp( SMESHGUI* theModule ) {
     if( !theModule )
@@ -819,10 +868,9 @@ namespace SMESH
         PW = mgr->integerValue( "SMESH", "highlight_width", 5 );
 
     // adjust highlight_width to the width of mesh entities
-    int aPointSize  = mgr->integerValue("SMESH", "node_size", 3);
     int aElem0DSize = mgr->integerValue("SMESH", "elem0d_size", 5);
     int aLineWidth  = mgr->integerValue("SMESH", "element_width", 1);
-    int maxSize = aPointSize;
+    int maxSize = aElem0DSize;
     if (aElem0DSize > maxSize) maxSize = aElem0DSize;
     if (aLineWidth > maxSize) maxSize = aLineWidth;
     if (PW < maxSize + 2) PW = maxSize + 2;
@@ -1161,4 +1209,148 @@ namespace SMESH
 
     }
   }
+
+  //----------------------------------------------------------------------------
+  // internal function
+  void ComputeBoundsParam( vtkFloatingPointType theBounds[6],
+                           vtkFloatingPointType theDirection[3],
+                           vtkFloatingPointType theMinPnt[3],
+                           vtkFloatingPointType& theMaxBoundPrj,
+                           vtkFloatingPointType& theMinBoundPrj )
+  {
+    //Enlarge bounds in order to avoid conflicts of precision
+    for(int i = 0; i < 6; i += 2){
+      static double EPS = 1.0E-3;
+      vtkFloatingPointType aDelta = (theBounds[i+1] - theBounds[i])*EPS;
+      theBounds[i] -= aDelta;
+      theBounds[i+1] += aDelta;
+    }
+
+    vtkFloatingPointType aBoundPoints[8][3] = { {theBounds[0],theBounds[2],theBounds[4]},
+                                                {theBounds[1],theBounds[2],theBounds[4]},
+                                                {theBounds[0],theBounds[3],theBounds[4]},
+                                                {theBounds[1],theBounds[3],theBounds[4]},
+                                                {theBounds[0],theBounds[2],theBounds[5]},
+                                                {theBounds[1],theBounds[2],theBounds[5]}, 
+                                                {theBounds[0],theBounds[3],theBounds[5]}, 
+                                                {theBounds[1],theBounds[3],theBounds[5]}};
+
+    int aMaxId = 0, aMinId = aMaxId;
+    theMaxBoundPrj = vtkMath::Dot(theDirection,aBoundPoints[aMaxId]);
+    theMinBoundPrj = theMaxBoundPrj;
+    for(int i = 1; i < 8; i++){
+      vtkFloatingPointType aTmp = vtkMath::Dot(theDirection,aBoundPoints[i]);
+      if(theMaxBoundPrj < aTmp){
+        theMaxBoundPrj = aTmp;
+        aMaxId = i;
+      }
+      if(theMinBoundPrj > aTmp){
+        theMinBoundPrj = aTmp;
+        aMinId = i;
+      }
+    }
+    vtkFloatingPointType *aMinPnt = aBoundPoints[aMaxId];
+    theMinPnt[0] = aMinPnt[0];
+    theMinPnt[1] = aMinPnt[1];
+    theMinPnt[2] = aMinPnt[2];
+  }
+
+  // internal function
+  void DistanceToPosition( vtkFloatingPointType theBounds[6],
+                           vtkFloatingPointType theDirection[3],
+                           vtkFloatingPointType theDist,
+                           vtkFloatingPointType thePos[3] )
+  {
+    vtkFloatingPointType aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
+    ComputeBoundsParam(theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
+    vtkFloatingPointType aLength = (aMaxBoundPrj-aMinBoundPrj)*theDist;
+    thePos[0] = aMinPnt[0]-theDirection[0]*aLength;
+    thePos[1] = aMinPnt[1]-theDirection[1]*aLength;
+    thePos[2] = aMinPnt[2]-theDirection[2]*aLength;
+  }
+
+  // internal function (currently unused, left just in case)
+  void PositionToDistance( vtkFloatingPointType theBounds[6],
+                           vtkFloatingPointType theDirection[3],
+                           vtkFloatingPointType thePos[3],
+                           vtkFloatingPointType& theDist )
+  {
+    vtkFloatingPointType aMaxBoundPrj, aMinBoundPrj, aMinPnt[3];
+    ComputeBoundsParam(theBounds,theDirection,aMinPnt,aMaxBoundPrj,aMinBoundPrj);
+    vtkFloatingPointType aPrj = vtkMath::Dot(theDirection,thePos);
+    theDist = (aPrj-aMinBoundPrj)/(aMaxBoundPrj-aMinBoundPrj);
+  }
+
+  bool ComputeClippingPlaneParameters( std::list<vtkActor*> theActorList,
+                                       vtkFloatingPointType theNormal[3],
+                                       vtkFloatingPointType theDist,
+                                       vtkFloatingPointType theBounds[6],
+                                       vtkFloatingPointType theOrigin[3] )
+  {
+    bool anIsOk = false;
+    theBounds[0] = theBounds[2] = theBounds[4] = VTK_DOUBLE_MAX;
+    theBounds[1] = theBounds[3] = theBounds[5] = -VTK_DOUBLE_MAX;
+    std::list<vtkActor*>::iterator anIter = theActorList.begin();
+    for( ; anIter != theActorList.end(); anIter++ ) {
+      if( vtkActor* aVTKActor = *anIter ) {
+        if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) ) {
+          vtkFloatingPointType aBounds[6];
+          anActor->GetUnstructuredGrid()->GetBounds( aBounds );
+          theBounds[0] = std::min( theBounds[0], aBounds[0] );
+          theBounds[1] = std::max( theBounds[1], aBounds[1] );
+          theBounds[2] = std::min( theBounds[2], aBounds[2] );
+          theBounds[3] = std::max( theBounds[3], aBounds[3] );
+          theBounds[4] = std::min( theBounds[4], aBounds[4] );
+          theBounds[5] = std::max( theBounds[5], aBounds[5] );
+          anIsOk = true;
+        }
+      }
+    }
+
+    if( !anIsOk )
+      return false;
+
+    DistanceToPosition( theBounds, theNormal, theDist, theOrigin );
+    return true;
+  }
+
+#ifndef DISABLE_PLOT2DVIEWER
+  //=======================================================================
+  /**
+     Get histogram from the input actor
+     Repaint/Remove the histogram in/from each opened Plot2D Viewer 
+  */
+  //=======================================================================
+  void ProcessIn2DViewers( SMESH_Actor *theActor, Viewer2dActionType aType ) {
+    SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>(SUIT_Session::session()->activeApplication());
+    
+    if(!anApp || !theActor)
+      return;
+
+    SPlot2d_Histogram* aHistogram = 0;
+    if(theActor->GetPlot2Histogram())
+      aHistogram = theActor->UpdatePlot2Histogram();
+    else 
+      return;
+      
+     ViewManagerList aViewManagerList;
+     anApp->viewManagers(SPlot2d_Viewer::Type(), aViewManagerList);
+     
+     aType = aHistogram->getPointList().empty() ? RemoveFrom2dViewer : aType;
+     
+     SUIT_ViewManager* aViewManager;
+     foreach( aViewManager, aViewManagerList ) {
+       if (Plot2d_ViewManager* aManager = dynamic_cast<Plot2d_ViewManager*>(aViewManager)) {
+        if (SPlot2d_Viewer* aViewer = dynamic_cast<SPlot2d_Viewer*>(aManager->getViewModel())) {
+          if (Plot2d_ViewFrame* aViewFrame = aViewer->getActiveViewFrame()) {
+            if(aType == UpdateIn2dViewer )
+              aViewFrame->displayObject(aHistogram, true);
+            else if (aType == RemoveFrom2dViewer)
+              aViewFrame->eraseObject(aHistogram, true);
+          }
+        }
+       }
+     }
+  }
+#endif //DISABLE_PLOT2DVIEWER
 } // end of namespace SMESH