]> OCCT Git - occt-copy.git/commitdiff
3D Offset algorithm extension for the cases with the shapes having the faces connecte...
authoremv <emv@opencascade.com>
Tue, 7 Jul 2015 11:18:28 +0000 (14:18 +0300)
committeremv <emv@opencascade.com>
Tue, 7 Jul 2015 11:18:28 +0000 (14:18 +0300)
src/BRepOffset/BRepOffset_Inter2d.cdl
src/BRepOffset/BRepOffset_Inter2d.cxx
src/BRepOffset/BRepOffset_Inter3d.cxx
src/BRepOffset/BRepOffset_MakeOffset.cxx

index d3929ae1e22e96c100e5eb60b9fa32cb418f9751..30ea15943a8d48f30632fc0015d467fee80c282d 100644 (file)
@@ -18,8 +18,8 @@
 
 class Inter2d from BRepOffset 
 
-       ---Purpose: Computes the intersections betwwen edges on a face
-       --          stores result is SD as AsDes from BRepOffset.
+        ---Purpose: Computes the intersections betwwen edges on a face
+        --          stores result is SD as AsDes from BRepOffset.
 
 uses
     AsDes               from BRepAlgo,
@@ -30,27 +30,28 @@ uses
     Real                from Standard
 
 is
-    Compute(myclass ; AsDes    : AsDes      from BRepAlgo;
-                     F        :         Face       from TopoDS;
-                             NewEdges :         IndexedMapOfShape from TopTools;
-                     Tol      :         Real       from Standard);
-                     
-       ---Purpose: Computes the intersections between the edges stored
-       --          is AsDes as descendants of <F> . Intersections is computed
-       --          between two edges if one of them is bound in NewEdges.
+    Compute(myclass ; AsDes    : AsDes             from BRepAlgo;
+                      F        : Face              from TopoDS;
+                      NewEdges : IndexedMapOfShape from TopTools;
+                      Tol      : Real              from Standard);
+                      
+              ---Purpose: Computes the intersections between the edges stored
+              --          is AsDes as descendants of <F> . Intersections is computed
+              --          between two edges if one of them is bound in NewEdges.
 
     
     --  Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 Begin
     --  Add another parameter: offset value.
     ConnexIntByInt(myclass ; 
-                  FI    :          Face                from TopoDS;
-                  OFI   : in out   Offset              from BRepOffset;
-                  MES   : in out   DataMapOfShapeShape from TopTools;  
-                  Build :          DataMapOfShapeShape from TopTools;  
-                  AsDes :  AsDes               from BRepAlgo; 
-                  Offset:          Real                from Standard;
-                  Tol   :          Real                from Standard);
+                   FI      :          Face                from TopoDS;
+                   OFI     : in out   Offset              from BRepOffset;
+                   MES     : in out   DataMapOfShapeShape from TopTools;  
+                   Build   :          DataMapOfShapeShape from TopTools;  
+                   AsDes   :          AsDes               from BRepAlgo; 
+                   AsDes2d :          AsDes               from BRepAlgo; 
+                   Offset  :          Real                from Standard;
+                   Tol     :          Real                from Standard);
     --  Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 End
-                           
+                            
 end Inter2d;
 
index 7e694d9f140e564bc94d0f18ab9e363bd8dff68e..43d7e32f7f9309e12c16b8839cd9c68589d627d7 100644 (file)
@@ -805,7 +805,6 @@ static void RefEdgeInter(const TopoDS_Face&              F,
   }
 }
 
-
 //======================================================================
 //function : EvaluateMaxSegment
 //purpose  : return MaxSegment to pass in approximation
@@ -1465,7 +1464,8 @@ void BRepOffset_Inter2d::ConnexIntByInt
  BRepOffset_Offset&            OFI,
  TopTools_DataMapOfShapeShape& MES,
  const TopTools_DataMapOfShapeShape& Build,
- const Handle(BRepAlgo_AsDes)&     AsDes,
+ const Handle(BRepAlgo_AsDes)& AsDes,
+ const Handle(BRepAlgo_AsDes)& AsDes2d,
  const Standard_Real           Offset,
  const Standard_Real           Tol)
 //  Modified by skv - Fri Dec 26 16:53:18 2003 OCC4455 End
@@ -1503,10 +1503,18 @@ void BRepOffset_Inter2d::ConnexIntByInt
       }
     } 
   }
-  
+
   TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
   if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));
-
+  //
+  TopTools_MapOfShape aME;
+  const TopTools_ListOfShape& aLE = AsDes->Descendant(FIO);
+  TopTools_ListIteratorOfListOfShape aItLE(aLE);
+  for (; aItLE.More(); aItLE.Next()) {
+    const TopoDS_Shape& aE = aItLE.Value();
+    aME.Add(aE);
+  }
+  //
   BRepAdaptor_Surface BAsurf(FIO);
   
   TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
@@ -1573,7 +1581,28 @@ void BRepOffset_Inter2d::ConnexIntByInt
         for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
           for (Exp2.Init(NE2,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) {
             RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),TopoDS::Edge(Exp2.Current()),
-                         AsDes,Tol,Standard_True/*Standard_False*/, Pref);
+                         AsDes2d,Tol,Standard_True/*Standard_False*/, Pref);
+          }
+        }
+        //
+        if (Build.IsBound(Vref)) {
+          TopoDS_Shape NE3 = Build(Vref);
+          //
+          for (Exp2.Init(NE3,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) {
+            const TopoDS_Edge& aE3 = *(TopoDS_Edge*)&Exp2.Current();
+            if (!aME.Contains(aE3)) {
+              continue;
+            }
+            //
+            for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
+              RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),aE3,
+                           AsDes2d,Tol,Standard_True/*Standard_False*/, Pref);
+            }
+            //
+            for (Exp1.Init(NE2,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
+              RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),aE3,
+                           AsDes2d,Tol,Standard_True/*Standard_False*/, Pref);
+            }
           }
         }
       }
@@ -1581,18 +1610,15 @@ void BRepOffset_Inter2d::ConnexIntByInt
         if (MES.IsBound(CEO)) {
           TopoDS_Vertex  V = CommonVertex(CEO,NEO); 
           UpdateVertex  (V,CEO,TopoDS::Edge(MES(CEO)),Tol);
-          AsDes->Add     (MES(CEO),V);
+          AsDes2d->Add     (MES(CEO),V);
         }
         else if (MES.IsBound(NEO)) {
           TopoDS_Vertex V = CommonVertex(CEO,NEO); 
           UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol);
-          AsDes->Add    (MES(NEO),V);
+          AsDes2d->Add    (MES(NEO),V);
         }
       }
       CurE = NextE;
     }
   }
 }
-
-
-
index 37c632ab163aa3bf66f87c3bff2ba9b45ce2340d..342747fd9429821ab3e83ea32dd90eea5073ed30 100644 (file)
@@ -40,6 +40,7 @@
 #include <Extrema_ExtPC.hxx>
 #include <TopTools_MapOfShape.hxx>
 #include <Precision.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
 
 
 
@@ -97,110 +98,53 @@ static void ExtentEdge(const TopoDS_Face& /*F*/,
 //function : SelectEdge
 //purpose  : 
 //=======================================================================
-
-static void SelectEdge (const TopoDS_Face& /*F*/,
-                        const TopoDS_Face& /*EF*/,
-                        const TopoDS_Edge& E,
-                        TopTools_ListOfShape& LInt)
+static void SelectEdge (const TopoDS_Shape& theS,
+                        TopTools_ListOfShape& theLE)
 {
-  //------------------------------------------------------------
-  // Proofing on the intersections on periodical faces
-  //------------------------------------------------------------
-   TopTools_ListIteratorOfListOfShape it(LInt);
-//  Modified by Sergey KHROMOV - Wed Jun  5 11:43:04 2002 Begin
-//   Standard_Real dU = 1.0e100;
-  Standard_Real dU = RealLast();
-//  Modified by Sergey KHROMOV - Wed Jun  5 11:43:05 2002 End
-  TopoDS_Edge   GE;
-
-  Standard_Real Fst, Lst, tmp;
-  BRep_Tool::Range(E, Fst, Lst);
-  BRepAdaptor_Curve  Ad1(E);
-  gp_Pnt PFirst = Ad1.Value( Fst );  
-  gp_Pnt PLast  = Ad1.Value( Lst );  
-
-//  Modified by Sergey KHROMOV - Wed Jun  5 11:23:10 2002 Begin
-   Extrema_ExtPC anExt;
-//  Modified by Sergey KHROMOV - Wed Jun  5 11:23:11 2002 End
-  //----------------------------------------------------------------------
-  // Selection of edge that coversmost of the domain of the initial edge.
-  //---------------------------------------------------------------------- 
-  for (; it.More(); it.Next()) {
-    const TopoDS_Edge& EI = TopoDS::Edge(it.Value());
-
-    BRep_Tool::Range(EI, Fst, Lst);
-    BRepAdaptor_Curve  Ad2(EI);
-
-//  Modified by Sergey KHROMOV - Wed Jun  5 11:25:03 2002 Begin
-    Standard_Integer i;
-    Standard_Real    aTol       = BRep_Tool::Tolerance(EI);
-    Standard_Boolean isMinFound = Standard_False;
-    Standard_Real    aSqrDist1  = Precision::Infinite();
-    Standard_Real    aSqrDist2  = Precision::Infinite();
-
-    anExt.Initialize(Ad2, Fst, Lst, aTol);
-
-// Seek for the min distance for PFirst:
-    anExt.Perform(PFirst);
-    if (anExt.IsDone()) {
-      for (i = 1; i <= anExt.NbExt(); i++) {
-        if (anExt.IsMin(i)) {
-          const gp_Pnt &aPMin = anExt.Point(i).Value();
-
-          aSqrDist1  = PFirst.SquareDistance(aPMin);
-          isMinFound = Standard_True;
-
-          break;
-        }
+  Standard_Real aT1, aT2, aDist, aDistMin;
+  TopExp_Explorer aExp;
+  TopTools_ListIteratorOfListOfShape aIt;
+  GeomAPI_ProjectPointOnCurve aProjPC;
+  gp_Pnt aPE1, aPE2;
+  TopoDS_Edge aRE;
+  //
+  aDistMin = RealLast();
+  //
+  aIt.Initialize(theLE);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Edge& aE = *(TopoDS_Edge*)&aIt.Value();
+    //
+    const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
+    //
+    aProjPC.Init(aC, aT1, aT2);
+    aPE1 = aC->Value(aT1);
+    aPE2 = aC->Value(aT2);
+    //
+    aDist = 0.;
+    aExp.Init(theS, TopAbs_VERTEX);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExp.Current();
+      const gp_Pnt aP = BRep_Tool::Pnt(aV);
+      //
+      aProjPC.Perform(aP);
+      if (aProjPC.NbPoints()) {
+        aDist += aProjPC.LowerDistance();
       }
-    }
-    if (!isMinFound) {
-      gp_Pnt aP1 = Ad2.Value(Fst);
-      gp_Pnt aP2 = Ad2.Value(Lst);
-
-      aSqrDist1 = Min(aP1.SquareDistance(PFirst), aP2.SquareDistance(PFirst));
-    }
-
-// Seek for the min distance for PLast:
-    isMinFound = Standard_False;
-    anExt.Perform(PLast);
-    if (anExt.IsDone()) {
-      for (i = 1; i <= anExt.NbExt(); i++) {
-        if (anExt.IsMin(i)) {
-          const gp_Pnt &aPMin = anExt.Point(i).Value();
-
-          aSqrDist2  = PLast.SquareDistance(aPMin);
-          isMinFound = Standard_True;
-
-          break;
-        }
+      else {
+        aDist += Min(aP.Distance(aPE1), aP.Distance(aPE2));
       }
     }
-    if (!isMinFound) {
-      gp_Pnt aP1 = Ad2.Value(Fst);
-      gp_Pnt aP2 = Ad2.Value(Lst);
-
-      aSqrDist2 = Min(aP1.SquareDistance(PLast), aP2.SquareDistance(PLast));
+    //
+    if (aDist < aDistMin) {
+      aDistMin = aDist;
+      aRE = aE;
     }
-
-    tmp = aSqrDist1 + aSqrDist2;
-//     gp_Pnt P1 = Ad2.Value(Fst);
-//     gp_Pnt P2 = Ad2.Value(Lst);
-       
-//     tmp = P1.Distance(PFirst) + P2.Distance(PLast);
-    if( tmp <= dU ) {
-      dU = tmp;
-      GE = EI;
-    } 
-//  Modified by Sergey KHROMOV - Wed Jun  5 11:24:54 2002 End
-
   }
-  LInt.Clear(); 
-  LInt.Append(GE);
+  //
+  theLE.Clear();
+  theLE.Append(aRE);
 }
 
-
 //=======================================================================
 //function : CompletInt
 //purpose  : 
@@ -482,103 +426,213 @@ void BRepOffset_Inter3d::ConnexIntByInt
  TopTools_ListOfShape&                  Failed)
 {
   //TopExp_Explorer Exp(SI,TopAbs_EDGE);
-  TopTools_IndexedMapOfShape Emap;
-  TopExp::MapShapes( SI, TopAbs_EDGE, Emap );
+  TopTools_IndexedMapOfShape VEmap;
+  TopTools_IndexedDataMapOfShapeListOfShape aMVF;
   TopoDS_Face     F1,F2,OF1,OF2,NF1,NF2;
   TopAbs_State    CurSide = mySide;
   BRep_Builder    B;
-  TopTools_ListIteratorOfListOfShape it;
-
-  //for (; Exp.More(); Exp.Next()) {
-  for (Standard_Integer i = 1; i <= Emap.Extent(); i++) {
-    //const TopoDS_Edge&               E = TopoDS::Edge(Exp.Current());
-    const TopoDS_Edge& E = TopoDS::Edge(Emap(i));
-    const BRepOffset_ListOfInterval& L = Analyse.Type(E);
-    if (!L.IsEmpty()) {
+  Standard_Boolean bEdge;
+  Standard_Integer i, aNb;
+  TopTools_ListIteratorOfListOfShape it, it1, itF1, itF2;
+  //
+  TopExp::MapShapes(SI, TopAbs_EDGE  , VEmap);
+  TopExp::MapShapes(SI, TopAbs_VERTEX, VEmap);
+  TopExp::MapShapesAndAncestors(SI, TopAbs_VERTEX, TopAbs_FACE, aMVF);
+  //
+  aNb = VEmap.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aS = VEmap(i);
+    //
+    TopoDS_Edge E;
+    TopTools_ListOfShape aLF1, aLF2;
+    //
+    bEdge = (aS.ShapeType() == TopAbs_EDGE);
+    if (bEdge) {
+      // faces connected by the edge
+      E = *(TopoDS_Edge*)&aS;
+      //
+      const BRepOffset_ListOfInterval& L = Analyse.Type(E);
+      if (L.IsEmpty()) {
+        continue;
+      }
+      //
       BRepOffset_Type    OT   = L.First().Type();
-      if (OT == BRepOffset_Convex || OT == BRepOffset_Concave) {
-        if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
-        else                          CurSide = TopAbs_OUT;
-        //-----------------------------------------------------------
-        // edge is of the proper type, return adjacent faces.
-        //-----------------------------------------------------------
-        const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
-        if (Anc.Extent() != 2) continue;
-        F1  = TopoDS::Face(Anc.First());
-        F2  = TopoDS::Face(Anc.Last ());
-        OF1 = TopoDS::Face(MapSF(F1).Face()); OF2 = TopoDS::Face(MapSF(F2).Face());
-        if (!MES.IsBound(OF1)) {
-          Standard_Boolean enlargeU = Standard_True;
-          Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
-          BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
-          BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
-          MES.Bind(OF1,NF1);
+      if (OT != BRepOffset_Convex && OT != BRepOffset_Concave) {
+        continue;
+      }
+      //
+      if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
+      else                          CurSide = TopAbs_OUT;
+      //-----------------------------------------------------------
+      // edge is of the proper type, return adjacent faces.
+      //-----------------------------------------------------------
+      const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
+      if (Anc.Extent() != 2) {
+        continue;
+      }
+      //
+      F1  = TopoDS::Face(Anc.First());
+      F2  = TopoDS::Face(Anc.Last ());
+      //
+      aLF1.Append(F1);
+      aLF2.Append(F2);
+    }
+    else {
+      // faces connected by the vertex
+      const TopTools_ListOfShape& aLF = aMVF.FindFromKey(aS);
+      if (aLF.Extent() < 2) {
+        continue;
+      }
+      //
+      Standard_Boolean bVertexOnly = Standard_False;
+      TopTools_MapOfShape aMFence;
+      //
+      it.Initialize(aLF);
+      for (; it.More(); it.Next()) {
+        const TopoDS_Face& aFV1 = *(TopoDS_Face*)&it.Value();
+        if (!aMFence.Add(aFV1)) {
+          continue;
         }
-        else {
-          NF1 = TopoDS::Face(MES(OF1));
+        //
+        TopTools_MapOfShape aME;
+        TopExp_Explorer aExp(aFV1, TopAbs_EDGE);
+        for (; aExp.More(); aExp.Next()) {
+          aME.Add(aExp.Current());
         }
-        if (!MES.IsBound(OF2)) {
-          Standard_Boolean enlargeU = Standard_True;
-          Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
-          BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
-          BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
-          MES.Bind(OF2,NF2); 
+        //
+        it1.Initialize(aLF);
+        for (it1.Next(); it1.More(); it1.Next()) {
+          const TopoDS_Face& aFV2 = *(TopoDS_Face*)&it1.Value();
+          if (aMFence.Contains(aFV2)) {
+            continue;
+          }
+          //
+          bVertexOnly = Standard_True;
+          aExp.Init(aFV2, TopAbs_EDGE);
+          for (; aExp.More(); aExp.Next()) {
+            const TopoDS_Shape& aEV2 = aExp.Current();
+            if (aME.Contains(aEV2)) {
+              bVertexOnly = Standard_False;
+              break;
+            }
+          }
+          //
+          if (bVertexOnly) {
+            aLF1.Append(aFV1);
+            aLF2.Append(aFV2);
+            aMFence.Add(aFV2);
+          }
         }
-        else {
-          NF2 = TopoDS::Face(MES(OF2));
+      }
+      //
+      if (aLF1.IsEmpty()) {
+        continue;
+      }
+      //
+      CurSide = mySide;
+    }
+    //
+    itF1.Initialize(aLF1);
+    itF2.Initialize(aLF2);
+    for (; itF1.More() && itF2.More(); itF1.Next(), itF2.Next()) {
+      F1 = TopoDS::Face(itF1.Value());
+      F2 = TopoDS::Face(itF2.Value());
+      //
+      OF1 = TopoDS::Face(MapSF(F1).Face());
+      OF2 = TopoDS::Face(MapSF(F2).Face());
+      if (!MES.IsBound(OF1)) {
+        Standard_Boolean enlargeU = Standard_True;
+        Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
+        BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
+        BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
+        MES.Bind(OF1,NF1);
+      }
+      else {
+        NF1 = TopoDS::Face(MES(OF1));
+      }
+      //
+      if (!MES.IsBound(OF2)) {
+        Standard_Boolean enlargeU = Standard_True;
+        Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True;
+        BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast );
+        BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast);
+        MES.Bind(OF2,NF2); 
+      }
+      else {
+        NF2 = TopoDS::Face(MES(OF2));
+      }
+      //
+      if (!IsDone(NF1,NF2)) {
+        TopTools_ListOfShape LInt1,LInt2;
+        BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,bEdge);
+        if (LInt1.Extent() > 1) { 
+          // intersection is in seceral edges (free sewing)
+          SelectEdge(aS, LInt1);
+          SelectEdge(aS, LInt2);
         }
-        if (!IsDone(NF1,NF2)) {
-          TopTools_ListOfShape LInt1,LInt2;
-          BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,Standard_True);
-          if (LInt1.Extent() > 1)
-            { 
-              // intersection is in seceral edges (free sewing)
-              SelectEdge( NF1, NF2, E, LInt1 );
-              SelectEdge( NF1, NF2, E, LInt2 );
-            }
-          SetDone(NF1,NF2);
-          if (!LInt1.IsEmpty()) {
-            Store (NF1,NF2,LInt1,LInt2);
-            TopoDS_Compound C;
-            B.MakeCompound(C);
-            for (it.Initialize(LInt1) ; it.More(); it.Next()) {
-              B.Add(C,it.Value());
+        SetDone(NF1,NF2);
+        if (!LInt1.IsEmpty()) {
+          Store (NF1,NF2,LInt1,LInt2);
+          //
+          TopoDS_Compound C;
+          B.MakeCompound(C);
+          //
+          if (Build.IsBound(aS)) {
+            const TopoDS_Shape& aSE = Build(aS);
+            TopExp_Explorer aExp(aSE, TopAbs_EDGE);
+            for (; aExp.More(); aExp.Next()) {
+              const TopoDS_Shape& aNE = aExp.Current();
+              B.Add(C, aNE);
             }
-            Build.Bind(E,C);
           }
-          else {
-            Failed.Append(E);
+          //
+          it.Initialize(LInt1);
+          for (; it.More(); it.Next()) {
+            const TopoDS_Shape& aNE = it.Value();
+            B.Add(C, aNE);
           }
-        } else { // IsDone(NF1,NF2)
-          //  Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin
-          const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1);
-          const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2);
-
-          if (!aLInt1.IsEmpty()) {
-            TopoDS_Compound C;
-            TopTools_ListIteratorOfListOfShape anIt2;
-
-            B.MakeCompound(C);
-
-            for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
-              const TopoDS_Shape &anE1 = it.Value();
-
-              for (anIt2.Initialize(aLInt2) ; anIt2.More(); anIt2.Next()) {
-                const TopoDS_Shape &anE2 = anIt2.Value();
-
-                if (anE1.IsSame(anE2))
-                  B.Add(C, anE1);
-              }
+          //
+          Build.Bind(aS,C);
+        }
+        else {
+          Failed.Append(aS);
+        }
+      } else { // IsDone(NF1,NF2)
+        //  Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin
+        const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1);
+        const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2);
+        
+        if (!aLInt1.IsEmpty()) {
+          TopoDS_Compound C;
+          B.MakeCompound(C);
+          //
+          if (Build.IsBound(aS)) {
+            const TopoDS_Shape& aSE = Build(aS);
+            TopExp_Explorer aExp(aSE, TopAbs_EDGE);
+            for (; aExp.More(); aExp.Next()) {
+              const TopoDS_Shape& aNE = aExp.Current();
+              B.Add(C, aNE);
             }
-            Build.Bind(E,C);
           }
-          else {
-            Failed.Append(E);
+          //
+          for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
+            const TopoDS_Shape &anE1 = it.Value();
+            //
+            for (it1.Initialize(aLInt2) ; it1.More(); it1.Next()) {
+              const TopoDS_Shape &anE2 = it1.Value();
+              
+              if (anE1.IsSame(anE2))
+                B.Add(C, anE1);
+            }
           }
+          Build.Bind(aS,C);
         }
-        //  Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
-      }          
+        else {
+          Failed.Append(aS);
+        }
+      }
     }
+    //  Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
   }
 }
 
@@ -603,10 +657,12 @@ void BRepOffset_Inter3d::ContextIntByInt
   TopoDS_Edge                      OE;
   TopoDS_Compound                  C;
   BRep_Builder                     B;
-  TopTools_ListIteratorOfListOfShape it;
-  Standard_Integer i;
-  
-  for (i = 1; i <= ContextFaces.Extent(); i++) {
+  TopTools_ListIteratorOfListOfShape it, itF;
+  Standard_Integer i, j, aNb, aNbVE;
+  Standard_Boolean bEdge;
+
+  aNb = ContextFaces.Extent();
+  for (i = 1; i <= aNb; i++) {
     const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i));
     myTouched.Add(CF);
     if (ExtentContext) {
@@ -616,89 +672,153 @@ void BRepOffset_Inter3d::ContextIntByInt
   }
   TopAbs_State Side = TopAbs_OUT;
  
-  for (i = 1; i <= ContextFaces.Extent(); i++) {
+  for (i = 1; i <= aNb; i++) {
     const TopoDS_Face& CF  = TopoDS::Face(ContextFaces(i));
     if (ExtentContext) WCF = TopoDS::Face(MES(CF));
     else               WCF = CF;
 
-    for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
-         exp.More(); exp.Next()) {
-      const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
-      if (!Analyse.HasAncestor(E)) {
-        //----------------------------------------------------------------
-        // the edges of faces of context that are not in the initial shape
-        // can appear in the result.
-        //----------------------------------------------------------------
-        if (!ExtentContext) {
-          myAsDes->Add(CF,E);
-          myNewEdges.Add(E);
-        }
-        else {
-          if (!MES.IsBound(E)) {
-            TopoDS_Edge NE;
-            Standard_Real f,l,Tol;
-            BRep_Tool::Range(E,f,l);
-            Tol = BRep_Tool::Tolerance(E);
-            ExtentEdge(CF,E,NE);
-            TopoDS_Vertex V1,V2;
-            TopExp::Vertices(E,V1,V2);
-            NE.Orientation(TopAbs_FORWARD);
-            myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
-            myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
-            TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
-            B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
-            aLocalShape = V2.Oriented(TopAbs_INTERNAL);
-            B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
-//            B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
-//            B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
-            NE.Orientation(E.Orientation());
-            myAsDes->Add(CF,NE);
-            myNewEdges.Add(NE);
-            MES.Bind(E,NE);
+    TopTools_IndexedMapOfShape VEmap;
+    TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
+    TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
+    //
+    aNbVE = VEmap.Extent();
+    for (j = 1; j <= aNbVE; ++j) {
+      const TopoDS_Shape& aS = VEmap(j);
+      //
+      bEdge = (aS.ShapeType() == TopAbs_EDGE);
+      //
+      TopoDS_Edge E;
+      TopTools_ListOfShape Anc;
+      //
+      if (bEdge) {
+        // faces connected by the edge
+        //
+        E = *(TopoDS_Edge*)&aS;
+        if (!Analyse.HasAncestor(E)) {
+          //----------------------------------------------------------------
+          // the edges of faces of context that are not in the initial shape
+          // can appear in the result.
+          //----------------------------------------------------------------
+          if (!ExtentContext) {
+            myAsDes->Add(CF,E);
+            myNewEdges.Add(E);
           }
           else {
-            TopoDS_Shape NE = MES(E);
-            TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation());
-            myAsDes->Add(CF,aLocalShape);
+            if (!MES.IsBound(E)) {
+              TopoDS_Edge NE;
+              Standard_Real f,l,Tol;
+              BRep_Tool::Range(E,f,l);
+              Tol = BRep_Tool::Tolerance(E);
+              ExtentEdge(CF,E,NE);
+              TopoDS_Vertex V1,V2;
+              TopExp::Vertices(E,V1,V2);
+              NE.Orientation(TopAbs_FORWARD);
+              myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED));
+              myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD));
+              TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL);
+              B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol);
+              aLocalShape = V2.Oriented(TopAbs_INTERNAL);
+              B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol);
+//            B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol);
+//            B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol);
+              NE.Orientation(E.Orientation());
+              myAsDes->Add(CF,NE);
+              myNewEdges.Add(NE);
+              MES.Bind(E,NE);
+            }
+            else {
+              TopoDS_Shape NE = MES(E);
+              TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation());
+              myAsDes->Add(CF,aLocalShape);
 //            myAsDes->Add(CF,NE.Oriented(E.Orientation()));
+            }
           }
-        }
-        continue;
-      } 
-      const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
-      const TopoDS_Face&          F   = TopoDS::Face(Anc.First());
-      OF = TopoDS::Face(MapSF(F).Face());
-      TopoDS_Shape aLocalShape = MapSF(F).Generated(E);
-      OE = TopoDS::Edge(aLocalShape);
-//      OE = TopoDS::Edge(MapSF(F).Generated(E));
-      if (!MES.IsBound(OF)) {
-        BRepOffset_Tool::EnLargeFace(OF,NF,1,1);
-        MES.Bind(OF,NF);
+          continue;
+        } 
+        Anc = Analyse.Ancestors(E);
       }
       else {
-        NF = TopoDS::Face(MES(OF));
-      }
-      if (!IsDone(NF,CF)) {
-        TopTools_ListOfShape LInt1,LInt2;
-        TopTools_ListOfShape LOE;
-        LOE.Append(OE);
-        BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,Standard_True);
-        SetDone(NF,CF);
-        if (!LInt1.IsEmpty()) {
-          Store (CF,NF,LInt1,LInt2);
-          if (LInt1.Extent() == 1) {
-            Build.Bind(E,LInt1.First());
+        // faces connected by the vertex
+        //
+        if (!Analyse.HasAncestor(aS)) {
+          continue;
+        }
+        //
+        const TopTools_ListOfShape& aLE = Analyse.Ancestors(aS);
+        it.Initialize(aLE);
+        for (; it.More(); it.Next()) {
+          const TopoDS_Edge& aE = *(TopoDS_Edge*)&it.Value();
+          //
+          if (BRep_Tool::Degenerated(aE)) {
+            continue;
           }
-          else {
-            B.MakeCompound(C);
-            for (it.Initialize(LInt1) ; it.More(); it.Next()) {
-              B.Add(C,it.Value());
+          //
+          if (VEmap.Contains(aE)) {
+            continue;
+          }
+          //
+          const TopTools_ListOfShape& aLF = Analyse.Ancestors(aE);
+          itF.Initialize(aLF);
+          for (; itF.More(); itF.Next()) {
+            const TopoDS_Shape& aF = itF.Value();
+            Standard_Boolean bAdd = Standard_True;
+            exp.Init(aF, TopAbs_EDGE);
+            for (; exp.More() && bAdd; exp.Next()) {
+              const TopoDS_Shape& aEF = exp.Current();
+              bAdd = !VEmap.Contains(aEF);
+            }
+            if (bAdd) {
+              Anc.Append(aF);
             }
-            Build.Bind(E,C);
           }
         }
+      }
+      //
+      itF.Initialize(Anc);
+      for (; itF.More(); itF.Next()) {
+        const TopoDS_Face& F = TopoDS::Face(itF.Value());
+        OF = TopoDS::Face(MapSF(F).Face());
+        TopoDS_Shape aLocalShape = MapSF(F).Generated(E);
+        OE = TopoDS::Edge(aLocalShape);
+//      OE = TopoDS::Edge(MapSF(F).Generated(E));
+        if (!MES.IsBound(OF)) {
+          BRepOffset_Tool::EnLargeFace(OF,NF,1,1);
+          MES.Bind(OF,NF);
+        }
         else {
-          Failed.Append(E);
+          NF = TopoDS::Face(MES(OF));
+        }
+        if (!IsDone(NF,CF)) {
+          TopTools_ListOfShape LInt1,LInt2;
+          TopTools_ListOfShape LOE;
+          LOE.Append(OE);
+          BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,bEdge);
+          SetDone(NF,CF);
+          if (!LInt1.IsEmpty()) {
+            Store (CF,NF,LInt1,LInt2);
+            if ((LInt1.Extent() == 1) && !Build.IsBound(aS)) {
+              Build.Bind(aS,LInt1.First());
+            }
+            else {
+              B.MakeCompound(C);
+              if (Build.IsBound(aS)) {
+                const TopoDS_Shape& aSE = Build(aS);
+                exp.Init(aSE, TopAbs_EDGE);
+                for (; exp.More(); exp.Next()) {
+                  const TopoDS_Shape& aNE = exp.Current();
+                  B.Add(C, aNE);
+                }
+              }
+              //
+              for (it.Initialize(LInt1) ; it.More(); it.Next()) {
+                B.Add(C,it.Value());
+              }
+              Build.Bind(aS,C);
+            }
+          }
+          else {
+            Failed.Append(aS);
+          }
         }
       }
     }
index 8e5e4aaa327f2c27eeaa44d672d6479b2546769c..6bb83429923a3c19238a1da870fd453e07a5bd68 100644 (file)
@@ -901,7 +901,9 @@ static void TrimEdge (TopoDS_Edge&                  NE,
   Standard_Real UMax = -UMin;
 
   const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
-  
+  //
+  Standard_Boolean bTrim = Standard_False;
+  //
   if (LE.Extent() > 1) {
     TopTools_ListIteratorOfListOfShape it (LE);
     for (; it.More(); it.Next()) {
@@ -909,16 +911,15 @@ static void TrimEdge (TopoDS_Edge&                  NE,
       if (NE.Orientation() == TopAbs_REVERSED)
         V.Reverse();
       //V.Orientation(TopAbs_INTERNAL);
-      if (!FindParameter(V, NE, U))
-        {
-          Standard_Real f, l;
-          Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
-          gp_Pnt thePoint = BRep_Tool::Pnt(V);
-          GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
-          if (Projector.NbPoints() == 0)
-            Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
-          U = Projector.LowerDistanceParameter();
-        }
+      if (!FindParameter(V, NE, U)) {
+        Standard_Real f, l;
+        Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
+        gp_Pnt thePoint = BRep_Tool::Pnt(V);
+        GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
+        if (Projector.NbPoints() == 0)
+          Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
+        U = Projector.LowerDistanceParameter();
+      }
       if (U < UMin) {
         UMin = U; V1   = V;
       }
@@ -926,6 +927,7 @@ static void TrimEdge (TopoDS_Edge&                  NE,
         UMax = U; V2   = V;
       }
     }
+    //
     if (V1.IsNull() || V2.IsNull()) {
       Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
     }
@@ -945,6 +947,19 @@ static void TrimEdge (TopoDS_Edge&                  NE,
       AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
       AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
       BRepLib::SameParameter(NE, aSameParTol, Standard_True);
+      //
+      bTrim = Standard_True;
+    }
+  }
+  //
+  if (!bTrim) {
+    if (!BRep_Tool::Degenerated(NE)) {
+      BRepAdaptor_Curve aBAC(NE);
+      if (!aBAC.IsClosed()) {
+        if (AsDes->HasAscendant(NE)) {
+          AsDes->Remove(NE);
+        }
+      }
     }
   }
 }
@@ -961,6 +976,10 @@ static void TrimEdge (TopoDS_Edge&                  NE,
 #include <BOPDS_VectorOfInterfVE.hxx>
 #include <BOPCol_DataMapOfShapeShape.hxx>
 #include <BOPTools_AlgoTools3D.hxx>
+#include <IntTools_Context.hxx>
+#include <BOPTools_AlgoTools.hxx>
+#include <CPnts_AbscissaPoint.hxx>
+#include <IntTools_ShrunkRange.hxx>
 
 //=======================================================================
 //function : SortFaces
@@ -1032,7 +1051,7 @@ static void SortFaces(const TopTools_ListOfShape& theLIm,
       TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
     }
     //
-    // find outer edges and check if they touche the first part of edges
+    // find outer edges and check if they touch the first part of edges
     aItLF.Initialize(aLFTmp);
     for (; aItLF.More(); aItLF.Next()) {
       const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
@@ -1044,8 +1063,7 @@ static void SortFaces(const TopTools_ListOfShape& theLIm,
           TopoDS_Vertex aV1, aV2;
           TopExp::Vertices(aE, aV1, aV2);
           //
-          bFlag = aMV.Contains(aV1) ||
-            aMV.Contains(aV2);
+          bFlag = aMV.Contains(aV1) || aMV.Contains(aV2);
         }
       }
       //
@@ -1192,6 +1210,64 @@ static void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
   }
 }
 
+//=======================================================================
+//function : IsMicroEdge
+//purpose  : 
+//=======================================================================
+static Standard_Boolean IsMicroEdge (const TopoDS_Edge& theEdge,
+                                     const Handle(IntTools_Context)& theCtx,
+                                     Standard_Real& theFuzz)
+{
+  TopoDS_Vertex aV1, aV2;
+  TopExp::Vertices(theEdge, aV1, aV2);
+  Standard_Boolean bNull = aV1.IsNull() || aV2.IsNull();
+  if (bNull) {
+    return Standard_False;
+  }
+  //
+  Standard_Boolean bMicro;
+  Standard_Real aT1, aT2;
+  IntTools_ShrunkRange aSR;
+  //
+  BRepAdaptor_Curve aBAC(theEdge);
+  //
+  aT1 = BRep_Tool::Parameter(aV1, theEdge);
+  aT2 = BRep_Tool::Parameter(aV2, theEdge);
+  if (aT2 < aT1) {
+    Standard_Real aTmp = aT1;
+    aT1 = aT2;
+    aT2 = aTmp;
+  }
+  //
+  aSR.SetContext(theCtx);
+  aSR.SetData(theEdge, aT1, aT2, aV1, aV2);
+  aSR.Perform();
+  bMicro = (aSR.ErrorStatus() != 0);
+  if (!bMicro) {
+    Standard_Real anEps, aTS1, aTS2, aTolV1, aTolV2;
+    //
+    aTolV1 = BRep_Tool::Tolerance(aV1);
+    aTolV2 = BRep_Tool::Tolerance(aV2);
+    //
+    anEps = aBAC.Resolution(aTolV1 + aTolV2);
+    if (anEps < 1.e-8) {
+      anEps = 1.e-8;
+    }
+    //
+    aSR.ShrunkRange(aTS1, aTS2);
+    bMicro = (aTS2 - aTS1) <= anEps;
+  }
+  //
+  if (bMicro) {
+    Standard_Real aLen = CPnts_AbscissaPoint::Length(aBAC);
+    if (aLen > theFuzz) {
+      theFuzz = aLen;
+    }
+  }
+  //
+  return bMicro;
+}
+
 //=======================================================================
 //function : BuildSplitsOfFaces
 //purpose  : 
@@ -1208,8 +1284,15 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
   BOPCol_ListIteratorOfListOfShape aIt;
   TopTools_ListIteratorOfListOfShape aItLF, aItLE, aItLE1;
   TopTools_DataMapOfShapeListOfShape anEImages;
+  BRep_Builder aBB;
+  TopoDS_Compound aFaces;
+  //
+  aBB.MakeCompound(aFaces);
   //
   // firstly it is necessary to fuse all the edges
+  Standard_Real aFuzz = 0.;
+  Handle(IntTools_Context) aCtx = new IntTools_Context();
+  //
   aItLF.Initialize(theLF);
   for (; aItLF.More(); aItLF.Next()) {
     const TopoDS_Shape& aF = aItLF.Value();
@@ -1221,41 +1304,41 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
       if (BRep_Tool::Degenerated(aE)) {
         continue;
       }
+      //
+      if (IsMicroEdge(aE, aCtx, aFuzz)) {
+        continue;
+      }
+      //
       aLS.Append(aE);
     }
   }
   //
   if (aLS.Extent() > 1) {
-    BOPAlgo_PaveFiller aPF;
+    BOPAlgo_Builder aGFE;
     //
-    aPF.SetArguments(aLS);
-    aPF.Perform();
-    if (aPF.ErrorStatus() == 0) {
-      BOPAlgo_Builder aGFE;
-      //
-      aGFE.SetArguments(aLS);
-      aGFE.PerformWithFiller(aPF);
-      if (aGFE.ErrorStatus() == 0) {
-        // fill map with edges images
-        aIt.Initialize(aLS);
-        for (; aIt.More(); aIt.Next()) {
-          const TopoDS_Shape& aE = aIt.Value();
-          //
-          const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
-          if (aLEIm.Extent()) {
-            anEImages.Bind(aE, aLEIm);
-          }
-        }
+    aGFE.SetArguments(aLS);
+    aGFE.SetFuzzyValue(aFuzz);
+    aGFE.Perform();
+    if (aGFE.ErrorStatus() == 0) {
+      // fill map with edges images
+      aIt.Initialize(aLS);
+      for (; aIt.More(); aIt.Next()) {
+        const TopoDS_Shape& aE = aIt.Value();
         //
-        UpdateOrigins(theOrigins, aGFE);
+        const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
+        if (aLEIm.Extent()) {
+          anEImages.Bind(aE, aLEIm);
+        }
       }
+      //
+      UpdateOrigins(theOrigins, aGFE);
     }
   }
   //
   // now we can split the faces
   aItLF.Initialize(theLF);
   for (; aItLF.More(); aItLF.Next()) {
-    const TopoDS_Shape& aF = aItLF.Value();
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
     //
     // the offset face
     aLS.Clear();
@@ -1279,6 +1362,7 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
       }
     }
     //
+    aFuzz = 0.;
     // the edges by which the offset face should be split
     const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
     aItLE.Initialize(aLE);
@@ -1292,7 +1376,12 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
         const TopTools_ListOfShape& aLEIm = anEImages.Find(aE);
         aItLE1.Initialize(aLEIm);
         for (; aItLE1.More(); aItLE1.Next()) {
-          const TopoDS_Shape& aEIm = aItLE1.Value();
+          const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aItLE1.Value();
+          // check for micro edge
+          if (IsMicroEdge(aEIm, aCtx, aFuzz)) {
+            continue;
+          }
+          //
           aLS.Append(aEIm);
           if (!aMFE.Contains(aEIm)) {
             ++iCountE;
@@ -1300,6 +1389,9 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
         }
       }
       else {
+        if (IsMicroEdge(aE, aCtx, aFuzz)) {
+          continue;
+        }
         aLS.Append(aE);
         if (!aMFE.Contains(aE)) {
           ++iCountE;
@@ -1313,12 +1405,14 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
     if (!iCountE) {
       aLFImages.Append(aF);
       theImage.Bind(aF, aLFImages);
+      aBB.Add(aFaces, aF);
       continue;
     }
     //
     BOPAlgo_Builder aGF;
     //
     aGF.SetArguments(aLS);
+    aGF.SetFuzzyValue(aFuzz);
     aGF.Perform();
     if (aGF.ErrorStatus()) {
       theLFailed.Append(aF);
@@ -1397,6 +1491,11 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
         aExp.Init(aFIm, TopAbs_EDGE);
         for (bKeep = Standard_True; aExp.More() && bKeep; aExp.Next()) {
           const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
+          //
+          if (BRep_Tool::Degenerated(aE)) {
+            continue;
+          }
+          //
           bKeep = aME.Contains(aE);
         }
         //
@@ -1431,11 +1530,20 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
         for (; aExp.More(); aExp.Next()) {
           const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
           //
+          if (BRep_Tool::Degenerated(aEIm)) {
+            continue;
+          }
+          //
           if (!theOrigins.Contains(aEIm)) {
             continue;
           }
           //
           const TopTools_ListOfShape& aLEOr = theOrigins.FindFromKey(aEIm);
+          const TopoDS_Shape& aSOr = aLEOr.First();
+          if (aSOr.ShapeType() != TopAbs_EDGE) {
+            bRem = Standard_False;
+            break;
+          }
           //
           if (aLEOr.Extent() > 1) {
             TopTools_MapOfShape aME, aMV;
@@ -1494,11 +1602,11 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
           }
         }
         //
-        if (bRem) {
+        if (bRem && !bKeep) {
           aLFImages.Remove(aItLE);
         }
         else {
-          if (bKeep) {
+          if (!bRem && bKeep) {
             aLFKeep.Append(aFIm);
           }
           aItLE.Next();
@@ -1531,20 +1639,41 @@ void BRepOffset_MakeOffset::BuildSplitsOfFaces
       theImage.Bind(aF, aLFImages);
     }
     else {
-      theLFailed.Append(aF);
+      BRepAdaptor_Surface aBAS(aF, Standard_False);
+      if (aBAS.GetType() != GeomAbs_Plane) {
+        theLFailed.Append(aF);
+      }
+    }
+    //
+    aItLE.Initialize(aLFImages);
+    for (; aItLE.More(); aItLE.Next()) {
+      const TopoDS_Shape& aFIm = aItLE.Value();
+      aBB.Add(aFaces, aFIm);
     }
   }
   //
   // fill history for edges
+  TopTools_IndexedMapOfShape aMFE;
+  TopExp::MapShapes(aFaces, TopAbs_EDGE, aMFE);
+  //
   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(anEImages);
   for (; aItEIm.More(); aItEIm.Next()) {
     const TopoDS_Shape& aE = aItEIm.Key();
     const TopTools_ListOfShape& aLEIm = aItEIm.Value();
-    if (theImage.HasImage(aE)) {
-      theImage.Add(aE, aLEIm);
-    }
-    else {
-      theImage.Bind(aE, aLEIm);
+    //
+    Standard_Boolean bHasImage = theImage.HasImage(aE);
+    aItLE.Initialize(aLEIm);
+    for (; aItLE.More(); aItLE.Next()) {
+      const TopoDS_Shape& aEIm = aItLE.Value();
+      if (aMFE.Contains(aEIm)) {
+        if (bHasImage) {
+          theImage.Add(aE, aEIm);
+        }
+        else {
+          theImage.Bind(aE, aEIm);
+          bHasImage = Standard_True;
+        }
+      }
     }
   }
 }
@@ -1645,7 +1774,7 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
 //  Modified by skv - Mon Jan 12 11:50:02 2004 OCC4455 Begin
 //    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myTol);
-    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes2d,myOffset, myTol);
+    BRepOffset_Inter2d::ConnexIntByInt (FI,MapSF(FI),MES,Build,AsDes,AsDes2d,myOffset, myTol);
 //  Modified by skv - Mon Jan 12 11:50:03 2004 OCC4455 End
   }
   //-----------------------------------------------------------
@@ -1661,78 +1790,95 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
   for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
     const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
     NF = MapSF(FI).Face();
-    if (MES.IsBound(NF)) {NF = TopoDS::Face(MES(NF));}
+    if (MES.IsBound(NF)) {
+      NF = TopoDS::Face(MES(NF));
+    }
+    //
     TopTools_MapOfShape View;
-    for (Exp2.Init(FI.Oriented(TopAbs_FORWARD),TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
-      const TopoDS_Edge& EI = TopoDS::Edge(Exp2.Current());
-      if (View.Add(EI)) {
-        if (Build.IsBound(EI)) {
-          NE = Build(EI);
-          if (NE.ShapeType() == TopAbs_EDGE) {
-            if (anOrigins.Contains(NE)) {
-              anOrigins.ChangeFromKey(NE).Append(EI);
-            }
-            else {
-              TopTools_ListOfShape aLSx;
-              aLSx.Append(EI);
-              anOrigins.Add(NE, aLSx);
-            }
-            //
-            if (NewEdges.Add(NE)) {
-              TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);
-            }
+    TopTools_IndexedMapOfShape VEmap;
+    Standard_Integer i, aNb;
+    //
+    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
+    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
+    //
+    aNb = VEmap.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopoDS_Shape& aS = VEmap(i);
+      if (!View.Add(aS)) {
+        continue;
+      }
+      //
+      if (Build.IsBound(aS)) {
+        NE = Build(aS);
+        if (NE.ShapeType() == TopAbs_EDGE) {
+          if (anOrigins.Contains(NE)) {
+            anOrigins.ChangeFromKey(NE).Append(aS);
           }
           else {
-            //------------------------------------------------------------
-            // The Intersections are on several edges.
-            // The pieces without intersections with neighbors  
-            // are removed from AsDes.
-            //------------------------------------------------------------
-            for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
-              TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
-              if (NewEdges.Add(NEC)) {
-                NEC.Free(Standard_True);
-                if (anOrigins.Contains(NEC)) {
-                  anOrigins.ChangeFromKey(NEC).Append(EI);
-                }
-                else {
-                  TopTools_ListOfShape aLSx;
-                  aLSx.Append(EI);
-                  anOrigins.Add(NEC, aLSx);
-                }
-                //
-                if (!AsDes2d->Descendant(NEC).IsEmpty()) {
-                  TrimEdge (NEC,AsDes2d,AsDes);
-                }
-                else {
+            TopTools_ListOfShape aLSx;
+            aLSx.Append(aS);
+            anOrigins.Add(NE, aLSx);
+          }
+          //
+          if (NewEdges.Add(NE)) {
+            TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);
+          }
+        }
+        else {
+          //------------------------------------------------------------
+          // The Intersections are on several edges.
+          // The pieces without intersections with neighbors  
+          // are removed from AsDes.
+          //------------------------------------------------------------
+          for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
+            TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
+            if (NewEdges.Add(NEC)) {
+              NEC.Free(Standard_True);
+              if (anOrigins.Contains(NEC)) {
+                anOrigins.ChangeFromKey(NEC).Append(aS);
+              }
+              else {
+                TopTools_ListOfShape aLSx;
+                aLSx.Append(aS);
+                anOrigins.Add(NEC, aLSx);
+              }
+              //
+              if (!AsDes2d->Descendant(NEC).IsEmpty()) {
+                TrimEdge (NEC,AsDes2d,AsDes);
+              }
+              else {
+                if (AsDes->HasAscendant(NEC)) {
                   AsDes->Remove(NEC);
                 }
               }
             }
           }
         }
-        else {
-          NE = MapSF(FI).Generated(EI);
-          
-          //// modified by jgv, 19.12.03 for OCC4455 ////
-          NE.Orientation( EI.Orientation() );
-          if (anOrigins.Contains(NE)) {
-            anOrigins.ChangeFromKey(NE).Append(EI);
-          }
-          else {
-            TopTools_ListOfShape aLSx;
-            aLSx.Append(EI);
-            anOrigins.Add(NE, aLSx);
-          }
-          ///////////////////////////////////////////////
-          if (MES.IsBound(NE)) {
-            NE = MES(NE);
-            NE.Orientation(EI.Orientation());
-            if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
-          }
-          AsDes->Add(NF,NE);
-        } 
       }
+      else {
+        if (aS.ShapeType() != TopAbs_EDGE) {
+          continue;
+        }
+        //
+        NE = MapSF(FI).Generated(aS);
+        //// modified by jgv, 19.12.03 for OCC4455 ////
+        NE.Orientation(aS.Orientation());
+        if (anOrigins.Contains(NE)) {
+          anOrigins.ChangeFromKey(NE).Append(aS);
+        }
+        else {
+          TopTools_ListOfShape aLSx;
+          aLSx.Append(aS);
+          anOrigins.Add(NE, aLSx);
+        }
+        //
+        if (MES.IsBound(NE)) {
+          NE = MES(NE);
+          NE.Orientation(aS.Orientation());
+          if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
+        }
+        AsDes->Add(NF,NE);
+      } 
     }
   }
   
@@ -3558,96 +3704,149 @@ void BRepOffset_MakeOffset::MakeShells()
     }
   }*/
   //
+  Standard_Boolean bFaces = !myFaces.IsEmpty();
+  //
   if ((myJoin == GeomAbs_Intersection) && myInter) {
     Standard_Integer i, aNb;
     TopTools_ListIteratorOfListOfShape aItLS, aItLS1;
+    BRep_Builder aBB;
+    //
+    TopoDS_Compound aCSF;
+    aBB.MakeCompound(aCSF);
     //
     BOPAlgo_Builder aGF;
     //
     aGF.SetArguments(aLSF);
     aGF.Perform();
-    if (aGF.ErrorStatus() == 0) {
+    bDone = (aGF.ErrorStatus() == 0);
+    if (bDone) {
       const TopoDS_Shape& aR = aGF.Shape();
       TopExp_Explorer aExp(aR, TopAbs_FACE);
       aLSF.Clear();
       for (; aExp.More(); aExp.Next()) {
         const TopoDS_Shape& aF = aExp.Current();
         aLSF.Append(aF);
+        aBB.Add(aCSF, aF);
       }
       //
-      UpdateOrigins(anOrigins, aGF);
-    }
-    //
-    if (myFaces.IsEmpty()) {
-      BOPAlgo_MakerVolume aMV1;
-      //
-      aMV1.SetArguments(aLSF);
-      aMV1.SetIntersect(Standard_False);
-      //
-      aMV1.Perform();
-      bDone = (aMV1.ErrorStatus() == 0);
+      bDone = (myOffset > 0);
       if (bDone) {
-        TopoDS_Compound aShells;
-        BRep_Builder aBB;
+        UpdateOrigins(anOrigins, aGF);
+        //
+        BOPAlgo_MakerVolume aMV1;
         //
-        aBB.MakeCompound(aShells);
+        aMV1.AddArgument(aCSF);
+        aMV1.SetIntersect(Standard_False);
         //
-        TopoDS_Shape aResult = aMV1.Shape();
-        if (aResult.ShapeType() == TopAbs_COMPOUND) {
-          // collect faces attached to only one solid
-          BOPCol_IndexedDataMapOfShapeListOfShape aMFS;
-          BOPCol_ListOfShape aLSF2;
+        if (bFaces) {
+          aNb = myFaces.Extent();
+          for (i = 1; i <= aNb; ++i) {
+            const TopoDS_Shape& aFEx = myFaces(i);
+            aMV1.AddArgument(aFEx);
+          }
+          aMV1.SetIntersect(Standard_True);
+        }
+        //
+        aMV1.Perform();
+        bDone = (aMV1.ErrorStatus() == 0);
+        if (bDone) {
+          TopoDS_Compound aShells;
           //
-          BOPTools::MapShapesAndAncestors(aResult, TopAbs_FACE, TopAbs_SOLID, aMFS);
-          aNb = aMFS.Extent();
-          bDone = (aNb > 0);
+          aBB.MakeCompound(aShells);
           //
-          if (bDone) {
-            for (i = 1; i <= aNb; ++i) {
-              const TopoDS_Shape& aFx = aMFS.FindKey(i);
-              const BOPCol_ListOfShape& aLSx = aMFS(i);
-              if (aLSx.Extent() == 1) {
-                // check orientation
-                const TopoDS_Face& aF = *(TopoDS_Face*)&aFx;
-                if (!anOrigins.Contains(aF)) {
-                  aLSF2.Append(aFx);
-                  continue;
-                }
-                //
-                const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aFx);
-                aItLS.Initialize(aLFOr);
-                for (; aItLS.More(); aItLS.Next()) {
-                  const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value();
-                  //
-                  if (CheckNormals(aF, aFOr)) {
+          TopoDS_Shape aResult = aMV1.Shape();
+          //
+          // collect images of the faces
+          TopTools_MapOfShape aMFaces;
+          aNb = myFaces.Extent();
+          for (i = 1; i <= aNb; ++i) {
+            const TopoDS_Shape& aFEx = myFaces(i);
+            const TopTools_ListOfShape& aLFEx = aMV1.Modified(aFEx);
+            if (!aLFEx.IsEmpty()) {
+              aItLS.Initialize(aLFEx);
+              for (; aItLS.More(); aItLS.Next()) {
+                const TopoDS_Face& aFExIm = *(TopoDS_Face*)&aItLS.Value();
+                aMFaces.Add(aFExIm);
+              }
+            }
+            else {
+              aMFaces.Add(aFEx);
+            }
+          }
+          //
+          if (aResult.ShapeType() == TopAbs_COMPOUND) {
+            // collect faces attached to only one solid
+            BOPCol_IndexedDataMapOfShapeListOfShape aMFS;
+            BOPCol_ListOfShape aLSF2;
+            //
+            BOPTools::MapShapesAndAncestors(aResult, TopAbs_FACE, TopAbs_SOLID, aMFS);
+            aNb = aMFS.Extent();
+            bDone = (aNb > 0);
+            //
+            if (bDone) {
+              for (i = 1; i <= aNb; ++i) {
+                const TopoDS_Shape& aFx = aMFS.FindKey(i);
+                const BOPCol_ListOfShape& aLSx = aMFS(i);
+                if (aLSx.Extent() == 1) {
+                  // check orientation
+                  const TopoDS_Face& aF = *(TopoDS_Face*)&aFx;
+                  if (!anOrigins.Contains(aF)) {
                     aLSF2.Append(aFx);
-                    break;
+                    continue;
+                  }
+                  //
+                  const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aFx);
+                  aItLS.Initialize(aLFOr);
+                  for (; aItLS.More(); aItLS.Next()) {
+                    const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value();
+                    //
+                    if (CheckNormals(aF, aFOr)) {
+                      aLSF2.Append(aFx);
+                      break;
+                    }
                   }
                 }
               }
+              //
+              // make solid containing most outer faces
+              BOPAlgo_MakerVolume aMV2;
+              //
+              aMV2.SetArguments(aLSF2);
+              aMV2.SetIntersect(Standard_False);
+              //
+              aMV2.Perform();
+              bDone = (aMV2.ErrorStatus() == 0);
+              if (bDone) {
+                aResult = aMV2.Shape();
+              }
             }
+          }
+          //
+          TopExp_Explorer aExp(aResult, TopAbs_SHELL);
+          bDone = aExp.More();
+          for (; aExp.More(); aExp.Next()) {
+            const TopoDS_Shell& aSh = *(TopoDS_Shell*)&aExp.Current();
             //
-            // make solid containing most outer faces
-            BOPAlgo_MakerVolume aMV2;
-            //
-            aMV2.SetArguments(aLSF2);
-            aMV2.SetIntersect(Standard_False);
-            //
-            aMV2.Perform();
-            bDone = (aMV2.ErrorStatus() == 0);
-            if (bDone) {
-              aResult = aMV2.Shape();
+            TopoDS_Shell aShellNew;
+            if (bFaces) {
+              aBB.MakeShell(aShellNew);
+              //
+              TopExp_Explorer aExp(aSh, TopAbs_FACE);
+              for (; aExp.More(); aExp.Next()) {
+                const TopoDS_Face& aFSh = *(TopoDS_Face*)&aExp.Current();
+                if (!aMFaces.Contains(aFSh)) {
+                  aBB.Add(aShellNew, aFSh);
+                }
+              }
+            }
+            else {
+              aShellNew = aSh;
             }
+            //
+            aBB.Add(aShells, aShellNew);
           }
+          myOffsetShape = aShells;
         }
-        //
-        TopExp_Explorer aExp(aResult, TopAbs_SHELL);
-        bDone = aExp.More();
-        for (; aExp.More(); aExp.Next()) {
-          const TopoDS_Shape& aSh = aExp.Current();
-          aBB.Add(aShells, aSh);
-        }
-        myOffsetShape = aShells;
       }
     }
   }