]> SALOME platform Git repositories - modules/geom.git/blobdiff - src/GEOMImpl/GEOMImpl_PipeDriver.cxx
Salome HOME
Merge branch 'master' of https://git.salome-platform.org/git/modules/geom
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PipeDriver.cxx
index 2efea33f46564a4162e12d0c926f1304d3781a8b..a3f4c388a1fd1fdceeb0543aef05a5cbe38c229c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2014  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
@@ -6,7 +6,7 @@
 // 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.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -38,8 +38,6 @@
 #include <ShapeAnalysis_Edge.hxx>
 #include <ShapeFix_Face.hxx>
 #include <ShapeFix_Shell.hxx>
-#include <ShapeFix_Shape.hxx>
-#include <ShapeFix_ShapeTolerance.hxx>
 
 #include <BRep_Tool.hxx>
 #include <BRep_Builder.hxx>
@@ -47,8 +45,9 @@
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <BRepBuilderAPI_Sewing.hxx>
-#include <BRepCheck_Analyzer.hxx>
 #include <BRepGProp.hxx>
+#include <GeomFill_Trihedron.hxx>
+#include <GeomFill_CorrectedFrenet.hxx>
 #include <BRepOffsetAPI_MakePipe.hxx>
 #include <BRepOffsetAPI_MakePipeShell.hxx>
 
@@ -81,6 +80,7 @@
 #include <Geom_Conic.hxx>
 #include <Geom_BSplineCurve.hxx>
 #include <Geom_BSplineSurface.hxx>
+#include <GeomAdaptor_HCurve.hxx>
 #include <GeomFill_BSplineCurves.hxx>
 #include <GeomConvert_ApproxCurve.hxx>
 #include <GeomConvert.hxx>
@@ -117,6 +117,59 @@ GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
 {
 }
 
+//=======================================================================
+//function : EvaluateBestSweepMode
+//purpose  : auxilary for right call of MakePipe and MakePipeShell
+//=======================================================================
+static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine)
+{
+  GeomFill_Trihedron theMode = GeomFill_IsFrenet;
+  
+  TopExp_Explorer Explo(Spine, TopAbs_EDGE);
+  for (; Explo.More(); Explo.Next())
+  {
+    TopoDS_Edge anEdge = TopoDS::Edge(Explo.Current());
+    Standard_Real fpar, lpar;
+    Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
+    GeomAdaptor_Curve GAcurve(aCurve, fpar, lpar);
+    Handle(GeomAdaptor_HCurve) GAHcurve = new GeomAdaptor_HCurve(GAcurve);
+
+    Handle(GeomFill_CorrectedFrenet) aCorrFrenet = new GeomFill_CorrectedFrenet(Standard_True); //for evaluation
+    aCorrFrenet->SetCurve(GAHcurve);
+    GeomFill_Trihedron aMode = aCorrFrenet->EvaluateBestMode();
+    if (aMode == GeomFill_IsDiscreteTrihedron)
+    {
+      theMode = aMode;
+      break;
+    }
+    if (aMode == GeomFill_IsCorrectedFrenet)
+      theMode = aMode;
+  }
+
+  return theMode;
+}
+
+//=======================================================================
+//function : BuildPipeShell
+//purpose  : Builds a pipe shell. If failed, try to build in Descrete Trihedron
+//           mode. Returns Standard_True if the building is done successfully.
+//=======================================================================
+static Standard_Boolean BuildPipeShell(BRepOffsetAPI_MakePipeShell &theBuilder)
+{
+  theBuilder.Build();
+
+  Standard_Boolean isDone = theBuilder.IsDone();
+
+  if (!isDone) {
+    // Try to use Descrete Trihedron mode.
+    theBuilder.SetDiscreteMode();
+    theBuilder.Build();
+    isDone = theBuilder.IsDone();
+  }
+
+  return isDone;
+}
+
 //=======================================================================
 //function : FillForOtherEdges
 //purpose  : auxilary for CreatePipeForShellSections()
@@ -212,12 +265,17 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
   TopExp_Explorer expw2(FS2,TopAbs_WIRE);
   TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
   BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
+  GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
+  if (theBestMode == GeomFill_IsDiscreteTrihedron)
+    aBuilder.SetDiscreteMode();
   aBuilder.Add(aWire1, aLoc1);
   aBuilder.Add(aWire2, aLoc2);
   if (!aBuilder.IsReady()) {
     return false;
   }
-  aBuilder.Build();
+
+  BuildPipeShell(aBuilder);
+
   TopoDS_Shape aShape = aBuilder.Shape();
   /*
   TopoDS_Compound C;
@@ -642,6 +700,7 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
   TopTools_SequenceOfShape aSeqBases;
   TopTools_SequenceOfShape aSeqLocs;
   TopTools_SequenceOfShape aSeqFaces;
+  Standard_Boolean NeedCreateSolid = Standard_False;
 
   Standard_Integer i = 1;
   for (i = 1; i <= nbBases; i++) {
@@ -658,7 +717,6 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
 
     //if for section was specified face with a few wires then a few
     //    pipes were build and make solid
-    Standard_Boolean NeedCreateSolid = Standard_False;
     if (aTypeBase == TopAbs_SHELL) {
       // create wire as boundary contour if shell is no closed
       // get free boundary shapes
@@ -819,14 +877,17 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
   // and seguences of shapes, perform pipe for each
   // and make sewing after that
   double fp,lp;
-  Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
   gp_Pnt P1,P2;
   gp_Vec Vec1,Vec2;
-  C->D1(fp,P1,Vec1);
-  C->D1(lp,P2,Vec2);
-  double SumAng = fabs(Vec1.Angle(Vec2));
-  Vec1 = Vec2;
-  P1 = P2;
+  double SumAng = 0;
+  if ( Edges.Length() > 0 ) {
+    Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
+    C->D1(fp,P1,Vec1);
+    C->D1(lp,P2,Vec2);
+    SumAng = fabs(Vec1.Angle(Vec2));
+    Vec1 = Vec2;
+    P1 = P2;
+  }
   TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums;
   int LastLoc = 1;
   //cout<<"Edges.Length()="<<Edges.Length()<<endl;
@@ -876,6 +937,9 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
         num2 = SplitLocNums.Value(nn);
         // make pipe
         BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
+        GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW);
+        if (theBestMode == GeomFill_IsDiscreteTrihedron)
+          aBuilder.SetDiscreteMode();
         Standard_Integer nbShapes = aTmpSeqBases.Length();
         for (i=1; i<=nbShapes; i++) {
           TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
@@ -885,7 +949,9 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
         if (!aBuilder.IsReady()) {
           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
         }
-        aBuilder.Build();
+
+        BuildPipeShell(aBuilder);
+
         TopoDS_Shape resShape = aBuilder.Shape();
         aSeqRes.Append(resShape);
       }
@@ -904,6 +970,9 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
       }
       // make pipe for last part
       BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
+      GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW);
+      if (theBestMode == GeomFill_IsDiscreteTrihedron)
+        aBuilder.SetDiscreteMode();
       Standard_Integer nbShapes = aTmpSeqBases.Length();
       for (i=1; i<=nbShapes; i++) {
         TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
@@ -913,7 +982,9 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
       if (!aBuilder.IsReady()) {
         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
       }
-      aBuilder.Build();
+
+      BuildPipeShell(aBuilder);
+
       TopoDS_Shape resShape = aBuilder.Shape();
       aSeqRes.Append(resShape);
       // make sewing for result
@@ -931,6 +1002,9 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
   else {
       // old implementation without splitting
       BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
+      GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
+      if (theBestMode == GeomFill_IsDiscreteTrihedron)
+        aBuilder.SetDiscreteMode();
 
       Standard_Integer nbShapes = aSeqBases.Length();
       Standard_Integer step = nbShapes/nbBases;
@@ -963,22 +1037,20 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
       
         aBuilder.SetTolerance(aTolConf, aTolConf, aTolAng);
 
-        aBuilder.Build();
+        Standard_Boolean isDone = BuildPipeShell(aBuilder);
+
+        if (isDone && NeedCreateSolid) {
+          isDone = aBuilder.MakeSolid();
+        }
+
+        if (!isDone) {
+          Standard_ConstructionError::Raise("Pipe construction failure");
+        }
         aShape = aBuilder.Shape();
         aSeqFaces.Append(aShape);
         for (j = 1; j <=usedBases.Length(); j++)
           aBuilder.Delete(usedBases.Value(j));
       }
-
-      //for case if section is face
-      if (aSeqFaces.Length() >1) {
-        BRep_Builder aB;
-        TopoDS_Compound aComp;
-        aB.MakeCompound(aComp);
-        for (i = 1; i <= aSeqFaces.Length(); i++)
-          aB.Add(aComp,aSeqFaces.Value(i));
-        aShape = aComp;
-      }
   }
 
   return aShape;
@@ -1450,6 +1522,9 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
       if (!aWire1.IsNull() && !aWire2.IsNull()) {
         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
+        GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath);
+        if (theBestMode == GeomFill_IsDiscreteTrihedron)
+          aBuilder.SetDiscreteMode();
         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
                      aWithContact, aWithCorrect);
         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
@@ -1458,7 +1533,9 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
           if (aCI) delete aCI;
           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
         }
-        aBuilder.Build();
+
+        BuildPipeShell(aBuilder);
+
         TopoDS_Shape aShape = aBuilder.Shape();
         TopoDS_Shell aShell;
         B.MakeShell(aShell);
@@ -1685,6 +1762,9 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
         // make pipe using aWire1 and aWire2
         if (!aWire1.IsNull() && !aWire2.IsNull()) {
           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
+          GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath);
+          if (theBestMode == GeomFill_IsDiscreteTrihedron)
+            aBuilder.SetDiscreteMode();
           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
                        aWithContact, aWithCorrect);
           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
@@ -1693,7 +1773,9 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
             if (aCI) delete aCI;
             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
           }
-          aBuilder.Build();
+
+          BuildPipeShell(aBuilder);
+
           TopoDS_Shape aShape = aBuilder.Shape();
           TopoDS_Shell aShell;
           B.MakeShell(aShell);
@@ -2276,8 +2358,10 @@ static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
   gp_Vec aVec(BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
   gp_Dir BiNormal(aVec);
   PipeBuilder.SetMode(BiNormal);
-  PipeBuilder.Build();
-  if (aShapeBase.ShapeType() == TopAbs_FACE) {
+
+  Standard_Boolean isDone = BuildPipeShell(PipeBuilder);
+
+  if (isDone && aShapeBase.ShapeType() == TopAbs_FACE) {
       PipeBuilder.MakeSolid();
   }
 
@@ -2387,9 +2471,10 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
       if (FaceBuilder.IsDone())
         Sweep.SetMode(FaceBuilder.Face());
       Sweep.Add(Profile);
-      Sweep.Build();
-      
-      if (!Sweep.IsDone())
+
+      Standard_Boolean isDone = BuildPipeShell(Sweep);
+
+      if (!isDone)
       {
         if (aCI) delete aCI;
         Standard_ConstructionError::Raise("MakePipeShell failed");
@@ -2399,7 +2484,22 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
       
     }
     else
-      aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase);
+    {
+      GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
+      BRepOffsetAPI_MakePipe aMkPipe(aWirePath, aShapeBase, theBestMode);
+
+      if (aMkPipe.IsDone()) {
+        aShape = aMkPipe.Shape();
+      } else if (theBestMode != GeomFill_IsDiscreteTrihedron) {
+        // Try to use Descrete Trihedron mode.
+        BRepOffsetAPI_MakePipe aMkPipeDescrete
+          (aWirePath, aShapeBase, GeomFill_IsDiscreteTrihedron);
+
+        if (aMkPipeDescrete.IsDone()) {
+          aShape = aMkPipeDescrete.Shape();
+        }
+      }
+    }
   }
 
   //building pipe with different sections
@@ -2470,19 +2570,8 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
 
   if (aShape.IsNull()) return 0;
 
-  BRepCheck_Analyzer ana (aShape, Standard_False);
-  if (!ana.IsValid()) {
-    ShapeFix_ShapeTolerance aSFT;
-    aSFT.LimitTolerance(aShape,Precision::Confusion(),Precision::Confusion());
-    Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
-    aSfs->SetPrecision(Precision::Confusion());
-    aSfs->Perform();
-    aShape = aSfs->Shape();
-
-    ana.Init(aShape, Standard_False);
-    if (!ana.IsValid())
-      Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
-  }
+  if ( !GEOMUtils::CheckShape(aShape) && !GEOMUtils::FixShapeTolerance(aShape) ) 
+    Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
 
   if (aType != PIPE_BASE_PATH &&
       aType != PIPE_SHELLS_WITHOUT_PATH) {