0028467: Improve UnifySameDomain performance
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_UnifySameDomain.cxx
index 5f8e9ce..0ce6b76 100644 (file)
@@ -15,9 +15,6 @@
 
 
 #include <BRep_Builder.hxx>
-#include <BRep_CurveRepresentation.hxx>
-#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
-#include <BRep_TEdge.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepLib.hxx>
 #include <BRepLib_MakeEdge.hxx>
@@ -34,6 +31,7 @@
 #include <Geom_ElementarySurface.hxx>
 #include <Geom_Line.hxx>
 #include <Geom_OffsetSurface.hxx>
+#include <Geom_Plane.hxx>
 #include <Geom_RectangularTrimmedSurface.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom_SurfaceOfLinearExtrusion.hxx>
 #include <ShapeAnalysis_WireOrder.hxx>
 #include <ShapeBuild_Edge.hxx>
 #include <ShapeBuild_ReShape.hxx>
-#include <ShapeExtend_CompositeSurface.hxx>
-#include <ShapeFix_ComposeShell.hxx>
 #include <ShapeFix_Edge.hxx>
 #include <ShapeFix_Face.hxx>
-#include <ShapeFix_SequenceOfWireSegment.hxx>
 #include <ShapeFix_Shell.hxx>
 #include <ShapeFix_Wire.hxx>
-#include <ShapeFix_WireSegment.hxx>
-#include <ShapeUpgrade_RemoveLocations.hxx>
 #include <ShapeUpgrade_UnifySameDomain.hxx>
 #include <Standard_Type.hxx>
 #include <TColGeom2d_Array1OfBSplineCurve.hxx>
@@ -68,7 +61,6 @@
 #include <TColGeom2d_SequenceOfBoundedCurve.hxx>
 #include <TColGeom_Array1OfBSplineCurve.hxx>
 #include <TColGeom_HArray1OfBSplineCurve.hxx>
-#include <TColGeom_HArray2OfSurface.hxx>
 #include <TColGeom_SequenceOfSurface.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TColStd_MapOfInteger.hxx>
@@ -85,7 +77,6 @@
 #include <TopTools_SequenceOfShape.hxx>
 #include <gp_Circ.hxx>
 #include <BRepAdaptor_Curve.hxx>
-#include <BRepClass_FaceClassifier.hxx>
 #include <BRepAdaptor_Curve2d.hxx>
 #include <gp_Vec2d.hxx>
 
@@ -1229,37 +1220,6 @@ void ShapeUpgrade_UnifySameDomain::KeepShapes(const TopTools_MapOfShape& theShap
   }
 }
 
-//=======================================================================
-//function : putIntWires
-//purpose  : Add internal wires that are classified inside the face as a subshape,
-//           and remove them from the sequence
-//=======================================================================
-static void putIntWires(TopoDS_Shape& theFace, TopTools_SequenceOfShape& theWires)
-{
-  TopoDS_Face& aFace = TopoDS::Face(theFace);
-  for (Standard_Integer i=1; i <= theWires.Length(); i++)
-  {
-    TopoDS_Shape aWire = theWires(i);
-    gp_Pnt2d aP2d;
-    Standard_Boolean isP2d = Standard_False;
-    for (TopoDS_Iterator it(aWire); it.More() && !isP2d; it.Next())
-    {
-      const TopoDS_Edge& anEdge = TopoDS::Edge(it.Value());
-      Standard_Real aFirst, aLast;
-      Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(anEdge, aFace, aFirst, aLast);
-      aC2d->D0((aFirst + aLast) * 0.5, aP2d);
-      isP2d = Standard_True;
-    }
-    BRepClass_FaceClassifier aClass(aFace, aP2d, Precision::PConfusion());
-    if (aClass.State() == TopAbs_IN)
-    {
-      BRep_Builder().Add(aFace, aWire);
-      theWires.Remove(i);
-      i--;
-    }
-  }
-}
-
 //=======================================================================
 //function : UnifyFaces
 //purpose  : 
@@ -1290,6 +1250,24 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces()
   myShape = myContext->Apply(myShape);
 }
 
+//=======================================================================
+//function : SetFixWireModes
+//purpose  : 
+//=======================================================================
+
+static void SetFixWireModes(ShapeFix_Face& theSff)
+{
+  Handle(ShapeFix_Wire) aFixWire = theSff.FixWireTool();
+  aFixWire->FixSelfIntersectionMode() = 0;
+  aFixWire->FixNonAdjacentIntersectingEdgesMode() = 0;
+  aFixWire->FixLackingMode() = 0;
+  aFixWire->FixNotchedEdgesMode() = 0;
+  aFixWire->ModifyTopologyMode() = Standard_False;
+  aFixWire->ModifyRemoveLoopMode() = 0;
+  aFixWire->FixGapsByRangesMode() = Standard_False;
+  aFixWire->FixSmallMode() = 0;
+}
+
 //=======================================================================
 //function : IntUnifyFaces
 //purpose  : 
@@ -1306,10 +1284,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
   // map of processed shapes
   TopTools_MapOfShape aProcessed;
 
-  // Check status of the unification
-  Standard_Integer NbModif = 0;
-  Standard_Boolean hasFailed = Standard_False;
-
   // processing each face
   TopExp_Explorer exp;
   for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) {
@@ -1356,6 +1330,11 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
         continue;
       }
 
+      // for a planar face create and store pcurve of edge on face
+      // to speed up all operations
+      if (!mySafeInputMode && aBaseSurface->IsKind(STANDARD_TYPE(Geom_Plane)))
+        BRepLib::BuildPCurveForEdgeOnPlane(edge, aFace);
+
       // get normal of the face to compare it with normals of other faces
       gp_Dir aDN1;
       //
@@ -1416,8 +1395,6 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
       for (i = 1; i <= faces.Length(); i++) {
         TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF);
       }
-      if (mySafeInputMode)
-        UpdateMapOfShapes(myKeepShapes, myContext);
       // Collect keep edges and multi-connected edges, i.e. edges that are internal to
       // the set of selected faces and have connections to other faces.
       TopTools_ListOfShape aKeepEdges;
@@ -1506,13 +1483,12 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
 
     // all faces collected in the sequence. Perform union of faces
     if (faces.Length() > 1) {
-      NbModif++;
       TopoDS_Face aResult;
       BRep_Builder B;
       B.MakeFace(aResult,aBaseSurface,aBaseLocation,0);
       Standard_Integer nbWires = 0;
 
-      TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD)));
+      TopoDS_Face tmpF = TopoDS::Face(faces(1).Oriented(TopAbs_FORWARD));
 
       // connecting wires
       while (edges.Length()>0) {
@@ -1559,12 +1535,10 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
 
         // sorting any type of edges
         aWire.Closed (BRep_Tool::IsClosed (aWire));
-        aWire = TopoDS::Wire(myContext->Apply(aWire));
 
         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion());
         if (mySafeInputMode)
           sfw->SetContext(myContext);
-        sfw->FixEdgeCurves();
         sfw->FixReorder();
         Standard_Boolean isDegRemoved = Standard_False;
         if(!sfw->StatusReorder ( ShapeExtend_FAIL )) {
@@ -1584,12 +1558,11 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
           if(isDegRemoved)
             sfw->FixDegenerated();
         }
-        TopoDS_Wire aWireFixed = sfw->Wire();
-        myContext->Replace(aWire,aWireFixed);
+        aWire = sfw->Wire();
 
         // add resulting wire
         if(isEdge3d) {
-          B.Add(aResult,aWireFixed);
+          B.Add(aResult,aWire);
         }
         else  {
           // sorting edges
@@ -1639,99 +1612,25 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape
         }
       }
 
-      // perform substitution of face
-      myContext->Replace(myContext->Apply(aFace),aResult);
-
       ShapeFix_Face sff (aResult);
       //Initializing by tolerances
       sff.SetPrecision(Precision::Confusion());
       sff.SetMinTolerance(Precision::Confusion());
       sff.SetMaxTolerance(1.);
       //Setting modes
-      sff.FixOrientationMode() = 0;
-      //sff.FixWireMode() = 0;
-      sff.SetContext(myContext);
+      SetFixWireModes(sff);
+      if (mySafeInputMode)
+        sff.SetContext(myContext);
       // Applying the fixes
       sff.Perform();
-      if(sff.Status(ShapeExtend_FAIL))
-        hasFailed = Standard_True;
-
-      // breaking down to several faces
-      TopoDS_Shape theResult = myContext->Apply(aResult);
-      for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) {
-        TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD));
-        Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 );
-        grid->SetValue ( 1, 1, aBaseSurface );
-        Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid );
-        ShapeFix_ComposeShell CompShell;
-        CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision
-        CompShell.SetContext( myContext );
-
-        TopTools_SequenceOfShape parts, anIntWires;
-        ShapeFix_SequenceOfWireSegment wires;
-        for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) {
-          const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current());
-          // check if the wire is ordinary (contains non-internal edges)
-          Standard_Boolean isInternal = Standard_True;
-          for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next())
-            isInternal = (it.Value().Orientation() == TopAbs_INTERNAL);
-          if (isInternal)
-          {
-            // place internal wire separately
-            anIntWires.Append(aWire);
-          }
-          else
-          {
-            Handle(ShapeExtend_WireData) sbwd =
-              new ShapeExtend_WireData (aWire);
-            ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED );
-            wires.Append(seg);
-          }
-        }
-
-        CompShell.DispatchWires( parts, wires );
-        for (Standard_Integer j=1; j <= parts.Length(); j++ ) {
-          ShapeFix_Face aFixOrient(TopoDS::Face(parts(j)));
-          aFixOrient.SetContext(myContext);
-          aFixOrient.FixOrientation();
-          // put internal wires to faces
-          putIntWires(parts(j), anIntWires);
-        }
-
-        TopoDS_Shape CompRes;
-        if ( parts.Length() !=1 ) {
-          TopoDS_Shell S;
-          B.MakeShell ( S );
-          for ( i=1; i <= parts.Length(); i++ )
-            B.Add ( S, parts(i) );
-          S.Closed (BRep_Tool::IsClosed (S));
-          CompRes = S;
-        }
-        else CompRes = parts(1);
-
-        myContext->Replace(aCurrent,CompRes);
+      if(!sff.Status(ShapeExtend_FAIL))
+      {
+        // perform substitution of faces
+        aResult = sff.Face();
+        myContext->Merge(faces, aResult);
       }
-
-      const TopoDS_Shape aResult3 = myContext->Apply(theResult);
-      myContext->Merge(faces, aResult3);
     }
   } // end processing each face
-
-  //TopoDS_Shape aResult = Shape;
-  if (NbModif > 0 && !hasFailed) {
-    TopoDS_Shape aResult = myContext->Apply(theInpShape);
-
-    ShapeFix_Edge sfe;
-    if (!myContext.IsNull()) sfe.SetContext(myContext);
-    for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) {
-      TopoDS_Edge E = TopoDS::Edge(exp.Current());
-      sfe.FixVertexTolerance (E);
-      // ptv add fix same parameter
-      sfe.FixSameParameter(E, Precision::Confusion());
-    }
-
-    myContext->Replace(theInpShape, aResult);
-  }
 }
 
 //=======================================================================
@@ -1859,13 +1758,38 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
     TopoDS_Face aFace = TopoDS::Face(myContext->Apply(ChangedFaces.FindKey(i)));
     if (aFace.IsNull())
       continue;
-    Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
-    sff->SetContext(myContext);
-    sff->SetPrecision(aPrec);
-    sff->SetMinTolerance(aPrec);
-    sff->SetMaxTolerance(Max(1., aPrec*1000.));
-    sff->Perform();
-    TopoDS_Shape aNewFace = sff->Face();
+
+    // for a planar face create and store pcurve of edge on face
+    // to speed up all operations; but this is allowed only when non-safe mode in force
+    if (!mySafeInputMode)
+    {
+      TopLoc_Location aLoc;
+      Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace, aLoc);
+      aSurface = ClearRts(aSurface);
+      if (aSurface->IsKind(STANDARD_TYPE(Geom_Plane)))
+      {
+        TopTools_ListOfShape aLE;
+        for (TopExp_Explorer anEx(aFace, TopAbs_EDGE); anEx.More(); anEx.Next())
+          aLE.Append(anEx.Current());
+        BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFace);
+      }
+    }
+
+    ShapeFix_Face sff(aFace);
+    if (mySafeInputMode)
+      sff.SetContext(myContext);
+    sff.SetPrecision(aPrec);
+    sff.SetMinTolerance(aPrec);
+    sff.SetMaxTolerance(Max(1., aPrec*1000.));
+    sff.FixOrientationMode() = 0;
+    sff.FixAddNaturalBoundMode() = 0;
+    sff.FixIntersectingWiresMode() = 0;
+    sff.FixLoopWiresMode() = 0;
+    sff.FixSplitFaceMode() = 0;
+    sff.FixPeriodicDegeneratedMode() = 0;
+    SetFixWireModes(sff);
+    sff.Perform();
+    TopoDS_Shape aNewFace = sff.Face();
     myContext->Replace(aFace,aNewFace);
   }
 
@@ -1892,37 +1816,16 @@ void ShapeUpgrade_UnifySameDomain::UnifyEdges()
   myShape = myContext->Apply(myShape);
 }
 
-//=======================================================================
-//function : UnifyFacesAndEdges
-//purpose  : 
-//=======================================================================
-
-void ShapeUpgrade_UnifySameDomain::UnifyFacesAndEdges()
-{
-  UnifyFaces();
-  
-  /*
-  ShapeUpgrade_RemoveLocations RemLoc;
-  RemLoc.Remove(myShape);
-  myShape = RemLoc.GetResult();
-  */
-
-  UnifyEdges();
-}
-
 //=======================================================================
 //function : Build
 //purpose  : builds the resulting shape
 //=======================================================================
 void ShapeUpgrade_UnifySameDomain::Build() 
 {
-  if (myUnifyFaces && myUnifyEdges)
-    UnifyFacesAndEdges();
-
-  else if (myUnifyEdges)
-    UnifyEdges();
-  else if (myUnifyFaces)
+  if (myUnifyFaces)
     UnifyFaces();
+  if (myUnifyEdges)
+    UnifyEdges();
 
   // Fill the history of modifications during the operation
   FillHistory();