Salome HOME
Feature 0017291: EDF 591 SMESH : Visualization of the orientation of the normal vecto...
authorouv <ouv@opencascade.com>
Tue, 5 Aug 2008 09:43:34 +0000 (09:43 +0000)
committerouv <ouv@opencascade.com>
Tue, 5 Aug 2008 09:43:34 +0000 (09:43 +0000)
14 files changed:
resources/SalomeApp.xml
src/OBJECT/Makefile.am
src/OBJECT/SMESH_Actor.cxx
src/OBJECT/SMESH_Actor.h
src/OBJECT/SMESH_ActorDef.h
src/OBJECT/SMESH_ActorUtils.cxx
src/OBJECT/SMESH_DeviceActor.cxx
src/OBJECT/SMESH_DeviceActor.h
src/OBJECT/SMESH_FaceOrientationFilter.cxx [new file with mode: 0644]
src/OBJECT/SMESH_FaceOrientationFilter.h [new file with mode: 0644]
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_Selection.cxx
src/SMESHGUI/SMESHGUI_Selection.h
src/SMESHGUI/SMESH_msg_en.ts

index 8f4b7b0e87ef42fb7030be24295d70e10a09302b..699b8b52c583c663ea73c33226cf177847a13fcf 100644 (file)
@@ -12,6 +12,9 @@
     <parameter name="node_size"                    value="3" />
     <parameter name="element_width"                value="1" />
     <parameter name="shrink_coeff"                 value="75"/>
+    <parameter name="orientation_color"            value="255, 255, 255"/>
+    <parameter name="orientation_scale"            value="0.1"/>
+    <parameter name="orientation_3d_vectors"       value="false"/>
     <parameter name="selection_element_color"      value="255, 255,   0"/>
     <parameter name="selection_object_color"       value="255, 255, 255"/>
     <parameter name="selection_precision_element"  value="0.005"/>
index 23723718d23fb4157eb7ff6ddc2271f016b38b8a..5da7d38afcd8fd24d84caa1353cf84740850dc66 100644 (file)
@@ -32,7 +32,8 @@ salomeinclude_HEADERS = \
        SMESH_Actor.h \
         SMESH_Object.h \
        SMESH_ObjectDef.h \
-       SMESH_ActorUtils.h
+       SMESH_ActorUtils.h \
+       SMESH_FaceOrientationFilter.h
 
 
 # Libraries targets
@@ -43,7 +44,8 @@ dist_libSMESHObject_la_SOURCES = \
        SMESH_DeviceActor.cxx \
        SMESH_Actor.cxx \
        SMESH_ExtractGeometry.cxx \
-       SMESH_ActorUtils.cxx
+       SMESH_ActorUtils.cxx \
+       SMESH_FaceOrientationFilter.cxx
 
 libSMESHObject_la_CPPFLAGS = \
         $(KERNEL_CXXFLAGS) \
index b229191242b66fed56e432d2040e98c6ef6021f8..9655756f5154da9b34fa108c7114266f955b6dc7 100644 (file)
@@ -116,6 +116,8 @@ SMESH_ActorDef::SMESH_ActorDef()
   myIsShrinkable = false;
   myIsShrunk = false;
 
+  myIsFacesOriented = false;
+
   myControlsPrecision = -1;
   SUIT_ResourceMgr* mgr = SUIT_Session::session()->resourceMgr();
   if ( mgr && mgr->booleanValue( "SMESH", "use_precision", false ) )
@@ -512,6 +514,22 @@ void SMESH_ActorDef::SetCellsLabeled(bool theIsCellsLabeled)
 }
 
 
+void SMESH_ActorDef::SetFacesOriented(bool theIsFacesOriented)
+{
+  myIsFacesOriented = theIsFacesOriented;
+
+  my2DActor->SetFacesOriented(theIsFacesOriented);
+  my3DActor->SetFacesOriented(theIsFacesOriented);
+
+  myTimeStamp->Modified();
+}
+
+bool SMESH_ActorDef::GetFacesOriented()
+{
+  return myIsFacesOriented;
+}
+
+
 void 
 SMESH_ActorDef::
 SetControlMode(eControl theMode)
@@ -693,8 +711,8 @@ void SMESH_ActorDef::AddToRender(vtkRenderer* theRenderer){
   theRenderer->AddActor(myNodeActor);
   theRenderer->AddActor(myBaseActor);
 
-  theRenderer->AddActor(my3DActor);
-  theRenderer->AddActor(my2DActor);
+  my3DActor->AddToRender(theRenderer);
+  my2DActor->AddToRender(theRenderer);
 
   theRenderer->AddActor(my1DActor);
   theRenderer->AddActor(my1DExtActor);
@@ -721,8 +739,8 @@ void SMESH_ActorDef::RemoveFromRender(vtkRenderer* theRenderer){
   theRenderer->RemoveActor(my1DActor);
   theRenderer->RemoveActor(my1DExtActor);
 
-  theRenderer->RemoveActor(my2DActor);
-  theRenderer->RemoveActor(my3DActor);
+  my2DActor->RemoveFromRender(theRenderer);
+  my3DActor->RemoveFromRender(theRenderer);
 
   theRenderer->RemoveActor(myScalarBarActor);
   theRenderer->RemoveActor(myPointLabels);
@@ -770,7 +788,7 @@ bool SMESH_ActorDef::Init(TVisualObjPtr theVisualObj,
   //SetIsShrunkable(theGrid->GetNumberOfCells() > 10);
   SetIsShrunkable(true);
 
-  SetShrinkFactor( SMESH::GetFloat( "SMESH:shrink_coeff", 0.75 ) );
+  SetShrinkFactor( SMESH::GetFloat( "SMESH:shrink_coeff", 75 ) / 100. );
 
   int aMode = mgr->integerValue( "SMESH", "display_mode" );
   SetRepresentation(-1);
@@ -1266,6 +1284,9 @@ void SMESH_ActorDef::Update(){
   if(myIsCellsLabeled){
     SetCellsLabeled(myIsCellsLabeled);
   }
+  if(myIsFacesOriented){
+    SetFacesOriented(myIsFacesOriented);
+  }
   SetEntityMode(GetEntityMode());
   SetVisibility(GetVisibility());
   
index 04dd4ceaded1aa10efba45ecead63f1591a44031..638e9c9d514e68a85eb3e3ba72d7b9a9293c8566 100644 (file)
@@ -93,6 +93,9 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor
   virtual void SetCellsLabeled(bool theIsCellsLabeled) = 0;
   virtual bool GetCellsLabeled() = 0;
 
+  virtual void SetFacesOriented(bool theIsFacesOriented) = 0;
+  virtual bool GetFacesOriented() = 0;
+
   enum eControl{eNone, eLength, eLength2D, eFreeBorders, eFreeEdges, eMultiConnection, 
                eArea, eTaper, eAspectRatio, eMinimumAngle, eWarping, eSkew,
                eAspectRatio3D, eMultiConnection2D, eVolume3D};
index c1e55d41558f025ab4882e601c0356be2b8ce310..a087e08d3f063820308523088f1b38deaf9fd472 100644 (file)
@@ -168,6 +168,9 @@ class SMESH_ActorDef : public SMESH_Actor
   virtual void SetCellsLabeled(bool theIsCellsLabeled);
   virtual bool GetCellsLabeled(){ return myIsCellsLabeled;}
 
+  virtual void SetFacesOriented(bool theIsFacesOriented);
+  virtual bool GetFacesOriented();
+
   virtual void SetControlMode(eControl theMode);
   virtual eControl GetControlMode(){ return myControlMode;}
 
@@ -250,6 +253,8 @@ class SMESH_ActorDef : public SMESH_Actor
   TCippingPlaneCont myCippingPlaneCont;
   long myControlsPrecision;
 
+  bool myIsFacesOriented;
+
   SMESH_ActorDef();
   ~SMESH_ActorDef();
 
index cee51d0fb185c50ff9ead5d33e7fe6a009dbb101..946a93df908f2f6af9ae0894f7bf14182bd118d2 100644 (file)
@@ -62,7 +62,7 @@ namespace SMESH
     vtkFloatingPointType val = theDefault;
     SUIT_ResourceMgr* mgr = SUIT_Session::session()->resourceMgr();
     if( mgr )
-      val = (vtkFloatingPointType) mgr->doubleValue( theValue, theSection, theDefault );
+      val = (vtkFloatingPointType) mgr->doubleValue( theSection, theValue, theDefault );
 
     return val;
   }
index 8a7341b4913e6006ae2cd1d7954d49b06d598a02..2399636e5e682d314e92e95385e070aab0f9cb30 100644 (file)
@@ -31,6 +31,7 @@
 #include "SMESH_ExtractGeometry.h"
 #include "SMESH_ControlsDef.hxx"
 #include "SMESH_ActorUtils.h"
+#include "SMESH_FaceOrientationFilter.h"
 #include "VTKViewer_CellLocationsArray.h"
 
 #include <VTKViewer_Transform.h>
@@ -61,6 +62,8 @@
 #include <vtkImplicitBoolean.h>
 #include <vtkPassThroughFilter.h>
 
+#include <vtkRenderer.h>
+
 #include "utilities.h"
 
 #ifdef _DEBUG_
@@ -111,6 +114,21 @@ SMESH_DeviceActor
 
   for(int i = 0; i < 6; i++)
     myPassFilter.push_back(vtkPassThroughFilter::New());
+
+  // Orientation of faces
+  myIsFacesOriented = false;
+
+  vtkFloatingPointType anRGB[3] = { 1, 1, 1 };
+  SMESH::GetColor( "SMESH", "orientation_color", anRGB[0], anRGB[1], anRGB[2], QColor( 255, 255, 255 ) );
+
+  myFaceOrientationFilter = SMESH_FaceOrientationFilter::New();
+
+  myFaceOrientationDataMapper = vtkPolyDataMapper::New();
+  myFaceOrientationDataMapper->SetInput(myFaceOrientationFilter->GetOutput());
+
+  myFaceOrientation = vtkActor::New();
+  myFaceOrientation->SetMapper(myFaceOrientationDataMapper);
+  myFaceOrientation->GetProperty()->SetColor(anRGB[0], anRGB[1], anRGB[2]);
 }
 
 
@@ -138,6 +156,14 @@ SMESH_DeviceActor
   for(int i = 0, iEnd = myPassFilter.size(); i < iEnd; i++){
     myPassFilter[i]->Delete();
   }
+
+  // Orientation of faces
+  myFaceOrientationFilter->Delete();
+
+  myFaceOrientationDataMapper->RemoveAllInputs();
+  myFaceOrientationDataMapper->Delete();
+
+  myFaceOrientation->Delete();
 }
 
 
@@ -221,17 +247,13 @@ SMESH_DeviceActor
 
     anId++; // 3
     myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
-    myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
 
     anId++; // 4
     myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
     myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
-    myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
-    myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
 
     anId++; // 5
     myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
-    myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
 
     vtkLODActor::SetMapper( myMapper );
     Modified();
@@ -536,6 +558,7 @@ SMESH_DeviceActor
   mTime = max(mTime,myMergeFilter->GetMTime());
   mTime = max(mTime,myGeomFilter->GetMTime());
   mTime = max(mTime,myTransformFilter->GetMTime());
+  mTime = max(mTime,myFaceOrientationFilter->GetMTime());
   return mTime;
 }
 
@@ -576,6 +599,30 @@ SMESH_DeviceActor
 }
 
 
+void
+SMESH_DeviceActor
+::SetFacesOriented(bool theIsFacesOriented) 
+{
+  if ( vtkDataSet* aDataSet = myPassFilter[ 1 ]->GetOutput() )
+  {
+    myIsFacesOriented = theIsFacesOriented;
+    if( theIsFacesOriented )
+      myFaceOrientationFilter->SetInput( aDataSet );
+    UpdateFaceOrientation();
+  }
+}
+
+void
+SMESH_DeviceActor
+::UpdateFaceOrientation()
+{
+  bool aShowFaceOrientation = myIsFacesOriented;
+  aShowFaceOrientation &= GetVisibility();
+  aShowFaceOrientation &= myRepresentation == eSurface;
+  myFaceOrientation->SetVisibility(aShowFaceOrientation);
+}
+
+
 void
 SMESH_DeviceActor
 ::SetRepresentation(EReperesent theMode)
@@ -602,6 +649,7 @@ SMESH_DeviceActor
     GetProperty()->SetRepresentation(theMode);
   }
   myRepresentation = theMode;
+  UpdateFaceOrientation();
   GetProperty()->Modified();
   myMapper->Modified();
   Modified();
@@ -619,6 +667,7 @@ SMESH_DeviceActor
   }else{
     vtkLODActor::SetVisibility(false);
   }
+  UpdateFaceOrientation();
 }
 
 
@@ -633,6 +682,23 @@ SMESH_DeviceActor
 }
 
 
+void
+SMESH_DeviceActor
+::AddToRender(vtkRenderer* theRenderer)
+{
+  theRenderer->AddActor(this);
+  theRenderer->AddActor(myFaceOrientation);
+}
+
+void
+SMESH_DeviceActor
+::RemoveFromRender(vtkRenderer* theRenderer)
+{
+  theRenderer->RemoveActor(this);
+  theRenderer->RemoveActor(myFaceOrientation);
+}
+
+
 int
 SMESH_DeviceActor
 ::GetNodeObjId(int theVtkID)
index 5ec3be21d13866d0df50a08005c1e049a7605e4f..f8ed9af9d47731e16d6995b4bbfdfc7b02f9cc72 100644 (file)
@@ -52,6 +52,7 @@ class VTKViewer_TransformFilter;
 class VTKViewer_ExtractUnstructuredGrid;
 
 class SMESH_ExtractGeometry;
+class SMESH_FaceOrientationFilter;
 
 
 class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{
@@ -74,6 +75,11 @@ class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{
   virtual void SetTransform(VTKViewer_Transform* theTransform); 
   virtual unsigned long int GetMTime();
 
+  virtual void SetFacesOriented(bool theIsFacesOriented);
+  virtual bool GetFacesOriented() { return myIsFacesOriented; }
+
+  void UpdateFaceOrientation();
+
   vtkFloatingPointType GetShrinkFactor();
   void  SetShrinkFactor(vtkFloatingPointType value);
 
@@ -89,6 +95,9 @@ class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{
   virtual void SetVisibility(int theMode);
   virtual int GetVisibility();
 
+  virtual void AddToRender(vtkRenderer* theRenderer); 
+  virtual void RemoveFromRender(vtkRenderer* theRenderer);
+
   VTKViewer_ExtractUnstructuredGrid* GetExtractUnstructuredGrid();
   vtkUnstructuredGrid* GetUnstructuredGrid();
 
@@ -124,6 +133,11 @@ class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{
   vtkMergeFilter* myMergeFilter;
   VTKViewer_ExtractUnstructuredGrid* myExtractUnstructuredGrid;
 
+  bool myIsFacesOriented;
+  SMESH_FaceOrientationFilter* myFaceOrientationFilter;
+  vtkPolyDataMapper* myFaceOrientationDataMapper;
+  vtkActor* myFaceOrientation;
+
   bool myStoreClippingMapping;
   VTKViewer_GeometryFilter *myGeomFilter;
   VTKViewer_TransformFilter *myTransformFilter;
diff --git a/src/OBJECT/SMESH_FaceOrientationFilter.cxx b/src/OBJECT/SMESH_FaceOrientationFilter.cxx
new file mode 100644 (file)
index 0000000..e3d312e
--- /dev/null
@@ -0,0 +1,306 @@
+//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "SMESH_FaceOrientationFilter.h"
+#include "SMESH_ActorUtils.h"
+
+#include "SUIT_Session.h"
+#include "SUIT_ResourceMgr.h"
+
+#include <vtkCellData.h>
+#include <vtkDataSet.h>
+#include <vtkPolyData.h>
+#include <vtkObjectFactory.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+
+#include <vtkFloatArray.h>
+#include <vtkCellArray.h>
+#include <vtkMaskPoints.h>
+#include <vtkCellCenters.h>
+#include <vtkGlyph3D.h>
+#include <vtkGlyphSource2D.h>
+
+#include <QColor>
+
+#define PI   3.14159265359
+
+vtkCxxRevisionMacro(SMESH_FaceOrientationFilter, "$Revision$");
+vtkStandardNewMacro(SMESH_FaceOrientationFilter);
+
+/*!
+ * \class SMESH_FaceOrientationFilter
+ * Passive filter take a polydata as input and create a dataset as output.
+ */
+
+SMESH_FaceOrientationFilter::SMESH_FaceOrientationFilter()
+{
+  SUIT_ResourceMgr* mgr = SUIT_Session::session()->resourceMgr();
+  myOrientationScale = mgr->doubleValue( "SMESH", "orientation_scale", 0.1 );
+  my3dVectors = mgr->booleanValue( "SMESH", "orientation_3d_vectors", false );
+
+  myArrowPolyData = CreateArrowPolyData();
+
+  myFacePolyData = vtkPolyData::New();
+
+  myFaceCenters = vtkCellCenters::New();
+  myFaceCenters->SetInput(myFacePolyData);
+
+  myFaceMaskPoints = vtkMaskPoints::New();
+  myFaceMaskPoints->SetInput(myFaceCenters->GetOutput());
+  myFaceMaskPoints->SetOnRatio(1);
+
+  myGlyphSource = vtkGlyphSource2D::New();
+  myGlyphSource->SetGlyphTypeToThickArrow();
+  myGlyphSource->SetFilled(0);
+  myGlyphSource->SetCenter(0.5, 0.0, 0.0);
+
+  myBaseGlyph = vtkGlyph3D::New();
+  myBaseGlyph->SetInput(myFaceMaskPoints->GetOutput());
+  myBaseGlyph->SetVectorModeToUseVector();
+  myBaseGlyph->SetSource(my3dVectors ? myArrowPolyData : myGlyphSource->GetOutput());
+}
+
+SMESH_FaceOrientationFilter::~SMESH_FaceOrientationFilter()
+{
+  myArrowPolyData->Delete();
+  myFacePolyData->Delete();
+  myFaceCenters->Delete();
+  myFaceMaskPoints->Delete();
+  myGlyphSource->Delete();
+  myBaseGlyph->Delete();
+}
+
+vtkPolyData* SMESH_FaceOrientationFilter::CreateArrowPolyData()
+{
+  vtkPoints* points = vtkPoints::New();
+  vtkCellArray* polys = vtkCellArray::New();
+
+  float l1 = 0.8;
+  float l2 = 1.0;
+  int n = 16;
+  float r1 = 0.04;
+  float r2 = 0.08;
+  float angle = 2. * PI / n;
+  float p[3];
+  vtkIdType c3[3];
+  vtkIdType c4[4];
+
+  float p0[3] = { 0.0, 0.0, 0.0 };
+  float p1[3] = {  l1, 0.0, 0.0 };
+  float p2[3] = {  l2, 0.0, 0.0 };
+
+  points->InsertPoint( 0, p0 );
+  points->InsertPoint( 1, p1 );
+  points->InsertPoint( 2, p2 );
+
+  // shaft
+  for( int i = 0; i < n; i++ )
+  {
+    p[0] = 0;
+    p[1] = r1 * sin( i * angle );
+    p[2] = r1 * cos( i * angle );
+    points->InsertPoint( i + 3, p );
+
+    p[0] = l1;
+    points->InsertPoint( i + 3 + n, p );
+  }
+
+  // insert the last cells outside a loop
+  {
+    c3[0] = 0;
+    c3[1] = 3;
+    c3[2] = 3 + n - 1;
+    polys->InsertNextCell( 3, c3 );
+
+    c4[0] = 3;
+    c4[1] = 3 + n - 1;
+    c4[2] = 3 + 2 * n - 1;
+    c4[3] = 3 + n;
+    polys->InsertNextCell( 4, c4 );
+  }
+  for( int i = 0; i < n - 1; i++ )
+  {
+    c3[0] = 0;
+    c3[1] = i + 3;
+    c3[2] = i + 4;
+    polys->InsertNextCell( 3, c3 );
+
+    c4[0] = i + 3;
+    c4[1] = i + 4;
+    c4[2] = i + 4 + n;
+    c4[3] = i + 3 + n;
+    polys->InsertNextCell( 4, c4 );
+  }
+
+  // cone
+  for( int i = 0; i < n; i++ )
+  {
+    p[0] = l1;
+    p[1] = r2 * sin( i * angle );
+    p[2] = r2 * cos( i * angle );
+    points->InsertPoint( i + 3 + 2 * n, p );
+  }
+
+  // insert the last cells outside a loop
+  {
+    c3[0] = 1;
+    c3[1] = 3 + 2 * n;
+    c3[2] = 3 + 2 * n + n - 1;
+    polys->InsertNextCell( 3, c3 );
+
+    c3[0] = 2;
+    polys->InsertNextCell( 3, c3 );
+  }
+  for( int i = 0; i < n - 1; i++ )
+  {
+    c3[0] = 1;
+    c3[1] = 3 + i + 2 * n;
+    c3[2] = 3 + i + 2 * n + 1;
+    polys->InsertNextCell( 3, c3 );
+
+    c3[0] = 2;
+    polys->InsertNextCell( 3, c3 );
+  }
+
+  vtkPolyData* aPolyData = vtkPolyData::New();
+
+  aPolyData->SetPoints(points);
+  points->Delete();
+
+  aPolyData->SetPolys(polys);
+  polys->Delete();
+
+  return aPolyData;
+}
+
+void GetFaceParams( vtkCell* theFace, double theNormal[3], double& theSize ) 
+{
+  vtkPoints* aPoints = theFace->GetPoints();
+
+  // here we get first 3 points from the face and calculate the normal as a cross-product of vectors
+  double x0 = aPoints->GetPoint(0)[0], y0 = aPoints->GetPoint(0)[1], z0 = aPoints->GetPoint(0)[2];
+  double x1 = aPoints->GetPoint(1)[0], y1 = aPoints->GetPoint(1)[1], z1 = aPoints->GetPoint(1)[2];
+  double x2 = aPoints->GetPoint(2)[0], y2 = aPoints->GetPoint(2)[1], z2 = aPoints->GetPoint(2)[2];
+
+  theNormal[0] = ( y1 - y0 ) * ( z2 - z0 ) - ( z1 - z0 ) * ( y2 - y0 );
+  theNormal[1] = ( z1 - z0 ) * ( x2 - x0 ) - ( x1 - x0 ) * ( z2 - z0 );
+  theNormal[2] = ( x1 - x0 ) * ( y2 - y0 ) - ( y1 - y0 ) * ( x2 - x0 );
+
+  double* aBounds = theFace->GetBounds();
+  theSize = pow( pow( aBounds[1] - aBounds[0], 2 ) +
+                pow( aBounds[3] - aBounds[2], 2 ) +
+                pow( aBounds[5] - aBounds[4], 2 ), 0.5 );
+}
+
+/*!
+ * Execute method. Output calculation.
+ */
+int SMESH_FaceOrientationFilter::RequestData(
+  vtkInformation *request,
+  vtkInformationVector **inputVector,
+  vtkInformationVector *outputVector)
+{
+  // get the info objects
+  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  // get the input and ouptut
+  vtkDataSet *input = vtkDataSet::SafeDownCast(
+    inInfo->Get(vtkDataObject::DATA_OBJECT()));
+  vtkPolyData *output = vtkPolyData::SafeDownCast(
+    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  myFacePolyData->Initialize();
+  myFacePolyData->ShallowCopy(input);
+
+  vtkCellArray* aFaces = vtkCellArray::New();
+
+  vtkFloatArray* aVectors = vtkFloatArray::New();
+  aVectors->SetNumberOfComponents(3);
+
+  int anAllFaces = 0;
+  double anAverageSize = 0;
+
+  vtkIdList* aNeighborIds = vtkIdList::New();
+
+  for(int aCellId = 0, aNbCells = input->GetNumberOfCells(); aCellId < aNbCells; aCellId++)
+  {
+    vtkCell* aCell = input->GetCell(aCellId);
+
+    if( aCell->GetNumberOfFaces() == 0 && aCell->GetNumberOfPoints() > 2 ) // cell is a face
+    {
+      double aSize, aNormal[3];
+      GetFaceParams( aCell, aNormal, aSize );
+
+      aFaces->InsertNextCell(aCell);
+      aVectors->InsertNextTuple(aNormal);
+
+      anAllFaces++;
+      anAverageSize += aSize;
+
+      continue;
+    }
+
+    for(int aFaceId = 0, aNbFaces = aCell->GetNumberOfFaces(); aFaceId < aNbFaces; aFaceId++)
+    {
+      vtkCell* aFace = aCell->GetFace(aFaceId);
+
+      input->GetCellNeighbors( aCellId, aFace->PointIds, aNeighborIds );
+      if( aNeighborIds->GetNumberOfIds() > 0 )
+       continue;
+
+      double aSize, aNormal[3];
+      GetFaceParams( aFace, aNormal, aSize );
+
+      aFaces->InsertNextCell(aFace->GetPointIds());
+      aVectors->InsertNextTuple(aNormal);
+
+      anAllFaces++;
+      anAverageSize += aSize;
+    }
+  }
+  aNeighborIds->Delete();
+
+  myFacePolyData->SetPolys(aFaces);
+  aFaces->Delete();
+
+  myFacePolyData->GetCellData()->SetVectors(aVectors);
+  aVectors->Delete();
+
+  if( anAllFaces == 0 )
+    return 0;
+
+  anAverageSize /= anAllFaces;
+  anAverageSize *= myOrientationScale;
+
+  myBaseGlyph->SetScaleFactor( anAverageSize );
+  myBaseGlyph->Update();
+
+  output->ShallowCopy( myBaseGlyph->GetOutput() );
+
+  return 1;
+}
+
+int SMESH_FaceOrientationFilter::FillInputPortInformation(int, vtkInformation *info)
+{
+  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
+  return 1;
+}
diff --git a/src/OBJECT/SMESH_FaceOrientationFilter.h b/src/OBJECT/SMESH_FaceOrientationFilter.h
new file mode 100644 (file)
index 0000000..4c52c2d
--- /dev/null
@@ -0,0 +1,67 @@
+//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SMESH_FACEORIENTATIONFILTER_H
+#define SMESH_FACEORIENTATIONFILTER_H
+
+#include "SMESH_Object.h"
+
+#include <vtkPolyDataAlgorithm.h>
+
+class vtkCellCenters;
+class vtkGlyph3D;
+class vtkGlyphSource2D;
+class vtkMaskPoints;
+
+class SMESHOBJECT_EXPORT SMESH_FaceOrientationFilter : public vtkPolyDataAlgorithm
+{
+public:
+  vtkTypeRevisionMacro( SMESH_FaceOrientationFilter, vtkPolyDataAlgorithm );
+
+  /*!Create a new SMESH_FaceOrientationFilter.*/
+  static SMESH_FaceOrientationFilter *New();
+
+protected:
+  SMESH_FaceOrientationFilter();
+  virtual ~SMESH_FaceOrientationFilter();
+
+  virtual int RequestData(vtkInformation *, vtkInformationVector **,
+                          vtkInformationVector *); //generate output data
+
+  virtual int FillInputPortInformation(int port, vtkInformation *info);
+
+  vtkPolyData* CreateArrowPolyData();
+
+private:
+  SMESH_FaceOrientationFilter( const SMESH_FaceOrientationFilter& );  //!< Not implemented.
+  void operator=( const SMESH_FaceOrientationFilter& );               //!< Not implemented.
+
+private:
+  bool my3dVectors;
+  vtkFloatingPointType myOrientationScale;
+  vtkPolyData* myArrowPolyData;
+  vtkPolyData* myFacePolyData;
+  vtkCellCenters* myFaceCenters;
+  vtkMaskPoints* myFaceMaskPoints;
+  vtkGlyphSource2D* myGlyphSource;
+  vtkGlyph3D* myBaseGlyph;
+};
+
+#endif
index 9c5dab2b614e64766a441e920ca9761e5ffa91e1..7f5322540d0578e4764c423c1f4dbb69e23b3c2b 100644 (file)
@@ -1403,6 +1403,23 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     ::SetDisplayEntity(theCommandID);
   break;
 
+  case 221: // Orientation of faces
+    {
+      LightApp_SelectionMgr* mgr = selectionMgr();
+      SALOME_ListIO selected; mgr->selectedObjects( selected );
+
+      SALOME_ListIteratorOfListIO it(selected);
+      for( ; it.More(); it.Next()) {
+        Handle(SALOME_InteractiveObject) anIObject = it.Value();
+       if(anIObject->hasEntry()) {
+         if(SMESH_Actor *anActor = SMESH::FindActorByEntry(anIObject->getEntry())){
+           anActor->SetFacesOriented( !anActor->GetFacesOriented() );
+         }
+       }
+      }
+      break;
+    }
+
   case 214:                                    // UPDATE
     {
       if(checkLock(aStudy)) break;
@@ -2620,6 +2637,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction(  218, "FACES",          "ICON_DLG_TRIANGLE", 0, true );
   createSMESHAction(  219, "VOLUMES",        "ICON_DLG_TETRAS", 0, true );
   createSMESHAction(  220, "ALL" );
+  createSMESHAction(  221, "FACE_ORIENTATION", "", 0, true );
   createSMESHAction( 1100, "EDIT_HYPO" );
   createSMESHAction( 1101, "RENAME", "", Qt::Key_F2 );
   createSMESHAction( 1102, "UNASSIGN" );
@@ -3009,6 +3027,13 @@ void SMESHGUI::initialize( CAM_Application* app )
   popupMgr()->insert( action( 220 ), anId, -1 ); // ALL
   popupMgr()->setRule( action( 220 ), aDiffElemsInVTK + "&& isVisible && not( elemTypes in entityMode )", QtxPopupMgr::VisibleRule );
 
+  //-------------------------------------------------
+  // Orientation of faces
+  //-------------------------------------------------
+  popupMgr()->insert( action( 221 ), -1, -1 );
+  popupMgr()->setRule( action( 221 ), aMeshInVTK + "&& isVisible", QtxPopupMgr::VisibleRule);
+  popupMgr()->setRule( action( 221 ), "facesOrientationMode = 'IsOriented'", QtxPopupMgr::ToggleRule );
+
   //-------------------------------------------------
   // Color / Size
   //-------------------------------------------------
@@ -3355,6 +3380,18 @@ void SMESHGUI::createPreferences()
   setPreferenceProperty( shrink, "min", 0 );
   setPreferenceProperty( shrink, "max", 100 );
 
+  int orientGroup = addPreference( tr( "PREF_GROUP_FACES_ORIENTATION" ), meshTab );
+  setPreferenceProperty( orientGroup, "columns", 1 );
+
+  addPreference( tr( "PREF_ORIENTATION_COLOR" ), orientGroup, LightApp_Preferences::Color, "SMESH", "orientation_color" );
+  int orientScale = addPreference( tr( "PREF_ORIENTATION_SCALE" ), orientGroup, LightApp_Preferences::DblSpin, "SMESH", "orientation_scale" );
+
+  setPreferenceProperty( orientScale, "min", 0 );
+  setPreferenceProperty( orientScale, "max", 1 );
+  setPreferenceProperty( orientScale, "step", 0.1 );
+
+  addPreference( tr( "PREF_ORIENTATION_3D_VECTORS" ), orientGroup, LightApp_Preferences::Bool, "SMESH", "orientation_3d_vectors" );
+
   int selTab = addPreference( tr( "PREF_TAB_SELECTION" ) );
 
   int selGroup = addPreference( tr( "PREF_GROUP_SELECTION" ), selTab );
index 6ec33b7ce98b5baa7f0c675c9703a640b00a5ddd..4711f1d10fc8d5f557bc86c98da643bd1b055592 100644 (file)
@@ -115,7 +115,7 @@ QVariant SMESHGUI_Selection::parameter( const int ind, const QString& p ) const
   else if ( p=="isComputable" )  val = QVariant( isComputable( ind ) );
   else if ( p=="hasReference" )  val = QVariant( hasReference( ind ) );
   else if ( p=="isImported" )    val = QVariant( isImported( ind ) );
-
+  else if ( p=="facesOrientationMode" ) val = QVariant( facesOrientationMode( ind ) );
 
   if( val.isValid() )
     return val;
@@ -255,6 +255,22 @@ QString SMESHGUI_Selection::controlMode( int ind ) const
   return "eNone";
 }
 
+//=======================================================================
+//function : facesOrientationMode
+//purpose  : 
+//=======================================================================
+
+QString SMESHGUI_Selection::facesOrientationMode( int ind ) const
+{
+  SMESH_Actor* actor = getActor( ind );
+  if ( actor ) {
+    if ( actor->GetFacesOriented() )
+      return "IsOriented";
+    return "IsNotOriented";
+  }
+  return "Unknown";
+}
+
 //=======================================================================
 //function : isAutoColor
 //purpose  : 
@@ -494,6 +510,7 @@ bool SMESHGUI_Selection::isImported( const int ind ) const
   QString e = entry( ind );
   _PTR(SObject) SO = SMESH::GetActiveStudyDocument()->FindObjectID( e.toLatin1().constData() );
   bool res = false;
+  /*
   if( SO )
   {
     SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( SO ) );
@@ -503,5 +520,6 @@ bool SMESHGUI_Selection::isImported( const int ind ) const
       res = strlen( (char*)inf->fileName ) > 0;
     }
   }
+  */
   return res;
 }
index 4d1ba4a636f93df5238fe4b115bc3d75e13f5e56..dfcac17f65176a611c767d7a0a2466931778bfd2 100644 (file)
@@ -64,6 +64,7 @@ public:
   virtual QString         shrinkMode( int ) const;
   virtual QList<QVariant> entityMode( int ) const;
   virtual QString         controlMode( int ) const;
+  virtual QString         facesOrientationMode( int ) const;
   
   SMESH_Actor*            getActor( int ) const;
 
index bef24fd989bce3e26a94f8f6b0d3d9641b92200d..cf8fff44130e755c845354a20795fe779b56b7d2 100644 (file)
             <source>MEN_DEL_GROUP</source>
             <translation>Delete Groups</translation>
         </message>
+        <message>
+            <source>MEN_FACE_ORIENTATION</source>
+            <translation>Orientation of faces</translation>
+        </message>
         <message>
             <source>MEN_DISABLE_AUTO_COLOR</source>
             <translation>Disable auto color</translation>
@@ -1940,6 +1944,10 @@ Consider saving your work before application crash</translation>
             <source>STB_DEL_GROUP</source>
             <translation>Delete Groups</translation>
         </message>
+        <message>
+            <source>STB_FACE_ORIENTATION</source>
+            <translation>Orientation of faces</translation>
+        </message>
         <message>
             <source>STB_DISABLE_AUTO_COLOR</source>
             <translation>Disable auto color</translation>
@@ -2392,6 +2400,10 @@ Consider saving your work before application crash</translation>
             <source>TOP_DEL_GROUP</source>
             <translation>Delete Groups</translation>
         </message>
+        <message>
+            <source>TOP_FACE_ORIENTATION</source>
+            <translation>Orientation of faces</translation>
+        </message>
         <message>
             <source>TOP_DISABLE_AUTO_COLOR</source>
             <translation>Disable auto color</translation>
@@ -2796,6 +2808,18 @@ Please, create VTK viewer and try again</translation>
             <source>PREF_COLOR</source>
             <translation>Color</translation>
         </message>
+        <message>
+            <source>PREF_ORIENTATION_COLOR</source>
+            <translation>Color</translation>
+        </message>
+        <message>
+            <source>PREF_ORIENTATION_3D_VECTORS</source>
+            <translation>3D vectors</translation>
+        </message>
+        <message>
+            <source>PREF_ORIENTATION_SCALE</source>
+            <translation>Scale</translation>
+        </message>
         <message>
             <source>PREF_DISPLAY_ENTITY</source>
             <translation>Display entity</translation>
@@ -2828,6 +2852,10 @@ Please, create VTK viewer and try again</translation>
             <source>PREF_GROUP_EXPORT</source>
             <translation>Mesh export</translation>
         </message>
+        <message>
+            <source>PREF_GROUP_FACES_ORIENTATION</source>
+            <translation>Orientation of faces</translation>
+        </message>
         <message>
             <source>PREF_GROUP_COMPUTE</source>
             <translation>Mesh computation</translation>