Salome HOME
0023193: [CEA] Show sub-shapes with given tolerance
[modules/geom.git] / src / GEOMUtils / GEOMUtils.cxx
index 3773646b81075e591b47bbff9d0856bf6b321421..c359c25676034168ea8bb651a3c41c5d9db17964 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  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
 #include <Standard_NullObject.hxx>
 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
 
+#define MAX2(X, Y)    (Abs(X) > Abs(Y) ? Abs(X) : Abs(Y))
+#define MAX3(X, Y, Z) (MAX2(MAX2(X,Y), Z))
+
 #define STD_SORT_ALGO 1
 
+#define DEFAULT_TOLERANCE_TOLERANCE     1.e-02
+#define DEFAULT_MAX_TOLERANCE_TOLERANCE 1.e-06
+
 // When the following macro is defined, ShapeFix_ShapeTolerance function is used to set max tolerance of curve
 // in GEOMUtils::FixShapeCurves function; otherwise less restrictive BRep_Builder::UpdateEdge/UpdateVertex
 // approach is used
@@ -217,46 +223,6 @@ namespace
     return Standard_False;
   }
 
-  //=======================================================================
-  //function : ShapeToDouble
-  //purpose  : used by CompareShapes::operator()
-  //=======================================================================
-  std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting)
-  {
-    // Computing of CentreOfMass
-    gp_Pnt GPoint;
-    double Len;
-
-    if (S.ShapeType() == TopAbs_VERTEX) {
-      GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
-      Len = (double)S.Orientation();
-    }
-    else {
-      GProp_GProps GPr;
-      // BEGIN: fix for Mantis issue 0020842
-      if (isOldSorting) {
-        BRepGProp::LinearProperties(S, GPr);
-      }
-      else {
-        if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
-          BRepGProp::LinearProperties(S, GPr);
-        }
-        else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
-          BRepGProp::SurfaceProperties(S, GPr);
-        }
-        else {
-          BRepGProp::VolumeProperties(S, GPr);
-        }
-      }
-      // END: fix for Mantis issue 0020842
-      GPoint = GPr.CentreOfMass();
-      Len = GPr.Mass();
-    }
-
-    double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
-    return std::make_pair(dMidXYZ, Len);
-  }
-
   void parseWard( const GEOMUtils::LevelsList &theLevelList, std::string &treeStr )
   {
     treeStr.append( "{" );
@@ -329,6 +295,46 @@ namespace
 
 }
 
+//=======================================================================
+//function : ShapeToDouble
+//purpose  : used by CompareShapes::operator()
+//=======================================================================
+std::pair<double, double> GEOMUtils::ShapeToDouble (const TopoDS_Shape& S, bool isOldSorting)
+{
+  // Computing of CentreOfMass
+  gp_Pnt GPoint;
+  double Len;
+
+  if (S.ShapeType() == TopAbs_VERTEX) {
+    GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
+    Len = (double)S.Orientation();
+  }
+  else {
+    GProp_GProps GPr;
+    // BEGIN: fix for Mantis issue 0020842
+    if (isOldSorting) {
+      BRepGProp::LinearProperties(S, GPr);
+    }
+    else {
+      if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
+        BRepGProp::LinearProperties(S, GPr);
+      }
+      else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
+        BRepGProp::SurfaceProperties(S, GPr);
+      }
+      else {
+        BRepGProp::VolumeProperties(S, GPr);
+      }
+    }
+    // END: fix for Mantis issue 0020842
+    GPoint = GPr.CentreOfMass();
+    Len = GPr.Mass();
+  }
+
+  double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
+  return std::make_pair(dMidXYZ, Len);
+}
+
 //=======================================================================
 //function : GetPosition
 //purpose  :
@@ -1094,20 +1100,28 @@ bool GEOMUtils::CheckShape( TopoDS_Shape& shape,
 
 bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
                                    TopAbs_ShapeEnum type,
-                                   Standard_Real tolerance )
+                                   Standard_Real tolerance,
+                                   bool checkGeometry )
 {
   ShapeFix_ShapeTolerance aSft;
   aSft.LimitTolerance( shape, tolerance, tolerance, type );
   Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape( shape );
   aSfs->Perform();
   shape = aSfs->Shape();
-  return CheckShape( shape );
+  return CheckShape( shape, checkGeometry );
+}
+
+bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
+                                   Standard_Real tolerance,
+                                   bool checkGeometry )
+{
+  return FixShapeTolerance( shape, TopAbs_SHAPE, tolerance, checkGeometry );
 }
 
 bool GEOMUtils::FixShapeTolerance( TopoDS_Shape& shape,
-                                   Standard_Real tolerance )
+                                   bool checkGeometry )
 {
-  return FixShapeTolerance( shape, TopAbs_SHAPE, tolerance );
+  return FixShapeTolerance( shape, Precision::Confusion(), checkGeometry );
 }
 
 bool GEOMUtils::FixShapeCurves( TopoDS_Shape& shape )
@@ -1166,3 +1180,165 @@ bool GEOMUtils::Write( const TopoDS_Shape& shape, const char* fileName )
 {
   return BRepTools::Write( shape, fileName );
 }
+
+TopoDS_Shape GEOMUtils::ReduceCompound( const TopoDS_Shape& shape )
+{
+  TopoDS_Shape result = shape;
+
+  if ( shape.ShapeType() == TopAbs_COMPOUND ||
+       shape.ShapeType() == TopAbs_COMPSOLID ) {
+
+    TopTools_ListOfShape l;
+    
+    TopoDS_Iterator it ( shape );
+    for ( ; it.More(); it.Next() )
+      l.Append( it.Value() );
+    if ( l.Extent() == 1 && l.First() != shape )
+      result = ReduceCompound( l.First() );
+  }
+  
+  return result;
+}
+
+void GEOMUtils::MeshShape( const TopoDS_Shape shape,
+                           double deflection, bool theForced )
+{
+  Standard_Real aDeflection = ( deflection <= 0 ) ? DefaultDeflection() : deflection;
+  
+  // Is shape triangulated?
+  Standard_Boolean alreadyMeshed = true;
+  TopExp_Explorer ex;
+  TopLoc_Location aLoc;
+  for ( ex.Init( shape, TopAbs_FACE ); ex.More() && alreadyMeshed; ex.Next() ) {
+    const TopoDS_Face& aFace = TopoDS::Face( ex.Current() );
+    Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation( aFace, aLoc );
+    alreadyMeshed = !aPoly.IsNull(); 
+  }
+  
+  if ( !alreadyMeshed || theForced ) {
+    // Compute bounding box
+    Bnd_Box B;
+    BRepBndLib::Add( shape, B );
+    if ( B.IsVoid() )
+      return; // NPAL15983 (Bug when displaying empty groups) 
+    Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+    B.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
+    
+    // This magic line comes from Prs3d_ShadedShape.gxx in OCCT
+    aDeflection = MAX3(aXmax-aXmin, aYmax-aYmin, aZmax-aZmin) * aDeflection * 4;
+    
+    // Clean triangulation before compute incremental mesh
+    BRepTools::Clean( shape );
+    
+    // Compute triangulation
+    BRepMesh_IncrementalMesh mesh( shape, aDeflection ); 
+  }
+}
+
+double GEOMUtils::DefaultDeflection()
+{
+  return 0.001;
+}
+
+//=======================================================================
+//function : IsOpenPath
+//purpose  : 
+//=======================================================================
+bool GEOMUtils::IsOpenPath(const TopoDS_Shape &theShape)
+{
+  bool isOpen = true;
+
+  if (theShape.IsNull() == Standard_False) {
+    if (theShape.Closed()) {
+      // The shape is closed
+      isOpen = false;
+    } else {
+      const TopAbs_ShapeEnum aType = theShape.ShapeType();
+
+      if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) {
+        // Check if path ends are coinsident.
+        TopoDS_Vertex aV[2];
+
+        if (aType == TopAbs_EDGE) {
+          // Edge
+          TopExp::Vertices(TopoDS::Edge(theShape), aV[0], aV[1]);
+        } else {
+          // Wire
+          TopExp::Vertices(TopoDS::Wire(theShape), aV[0], aV[1]);
+        }
+
+        if (aV[0].IsNull() == Standard_False &&
+            aV[1].IsNull() == Standard_False) {
+          if (aV[0].IsSame(aV[1])) {
+            // The shape is closed
+            isOpen = false;
+          } else {
+            const Standard_Real aTol1 = BRep_Tool::Tolerance(aV[0]);
+            const Standard_Real aTol2 = BRep_Tool::Tolerance(aV[1]);
+            const gp_Pnt        aPnt1 = BRep_Tool::Pnt(aV[0]);
+            const gp_Pnt        aPnt2 = BRep_Tool::Pnt(aV[1]);
+
+            if (aPnt1.Distance(aPnt2) <= aTol1 + aTol2) {
+              // The shape is closed
+              isOpen = false;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return isOpen;
+}
+
+//=======================================================================
+//function : CompareToleranceValues
+//purpose  : 
+//=======================================================================
+int GEOMUtils::CompareToleranceValues(const double theTolShape,
+                                      const double theTolRef)
+{
+  const double aTolTol = Min(DEFAULT_MAX_TOLERANCE_TOLERANCE,
+                             theTolRef*DEFAULT_TOLERANCE_TOLERANCE);
+
+  int aResult = 0;
+
+  if (theTolShape < theTolRef - aTolTol) {
+    aResult = -1;
+  } else if (theTolShape > theTolRef + aTolTol) {
+    aResult = 1;
+  }
+
+  return aResult;
+}
+
+//=======================================================================
+//function : IsFitCondition
+//purpose  : 
+//=======================================================================
+bool GEOMUtils::IsFitCondition(const ComparisonCondition theCondition,
+                               const double              theTolShape,
+                               const double              theTolRef)
+{
+  const int aCompValue = CompareToleranceValues(theTolShape, theTolRef);
+  bool      isFit      = false;
+
+  switch (theCondition) {
+    case CC_GT:
+      isFit = aCompValue == 1;
+      break;
+    case GEOMUtils::CC_GE:
+      isFit = aCompValue != -1;
+      break;
+    case GEOMUtils::CC_LT:
+      isFit = aCompValue == -1;
+      break;
+    case GEOMUtils::CC_LE:
+      isFit = aCompValue != 1;
+      break;
+    default:
+      break;
+  }
+
+  return isFit;
+}