0022946: BRepFeat_SplitShape crashes on splitting a face by two edges
authorjgv <jgv@opencascade.com>
Fri, 6 Apr 2012 07:52:38 +0000 (11:52 +0400)
committerjgv <jgv@opencascade.com>
Fri, 6 Apr 2012 07:52:38 +0000 (11:52 +0400)
null check for pcurve added to avoid exceptions
Correction to avoid the regression: check after PutPCurve(edg,fac)

src/BRepFeat/BRepFeat_SplitShape.cdl
src/BRepFeat/BRepFeat_SplitShape.lxx
src/BRepTest/BRepTest_FeatureCommands.cxx
src/LocOpe/LocOpe_ProjectedWires.cdl
src/LocOpe/LocOpe_SplitShape.cdl
src/LocOpe/LocOpe_SplitShape.cxx
src/LocOpe/LocOpe_Spliter.cxx
src/LocOpe/LocOpe_WiresOnShape.cdl
src/LocOpe/LocOpe_WiresOnShape.cxx
src/LocOpe/LocOpe_WiresOnShape.lxx

index 2850b43..8f5ddb0 100755 (executable)
@@ -43,6 +43,7 @@ uses Spliter           from LocOpe,
      Face              from TopoDS,
      Wire              from TopoDS,
      Edge              from TopoDS,
+     Compound          from TopoDS,
      Vertex            from TopoDS,
      ListOfShape       from TopTools,
      ShapeModification from BRepBuilderAPI
@@ -94,6 +95,20 @@ is
 
        is static;
     
+    Add(me: in out; Comp: Compound from TopoDS;
+                   F: Face from TopoDS)
+       ---Purpose: Adds the compound <Comp> on the face <F>. The
+       --          compound <Comp> must consist of edges lying on the
+       --          face <F>. If edges are geometrically connected,
+       --          they must be connected topologically, i.e. they
+       --          must share common vertices.
+       --          
+       -- Raises NoSuchObject  if <F> does not belong to the original shape.
+       ---C++: inline
+       raises NoSuchObject from Standard,
+              ConstructionError from Standard
+
+       is static;
 
 
     Add(me: in out; E  : Edge from TopoDS;
index 650c80d..2019d52 100755 (executable)
@@ -84,6 +84,17 @@ inline void BRepFeat_SplitShape::Add(const TopoDS_Edge& E,
   myWOnShape->Bind(E,F);
 }
 
+//=======================================================================
+//function : Add
+//purpose  : 
+//=======================================================================
+
+inline void BRepFeat_SplitShape::Add(const TopoDS_Compound& Comp,
+                                    const TopoDS_Face& F)
+{
+  myWOnShape->Bind(Comp,F);
+}
+
 
 //=======================================================================
 //function : Add
index 5198d79..2e57e53 100755 (executable)
@@ -745,12 +745,12 @@ static Standard_Integer SPLS(Draw_Interpretor& ,
          return 1; // on n`a rien recupere
        }
        TopAbs_ShapeEnum wtyp = W.ShapeType();
-       if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && pick) {
+       if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && wtyp != TopAbs_COMPOUND && pick) {
          Standard_Real u,v;
          DBRep_DrawableShape::LastPick(W,u,v);
          wtyp = W.ShapeType();
        }
-       if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE) {
+       if (wtyp != TopAbs_WIRE && wtyp != TopAbs_EDGE && wtyp != TopAbs_COMPOUND) {
          EF = DBRep::Get(a[i]);
          break;
        }
@@ -761,9 +761,12 @@ static Standard_Integer SPLS(Draw_Interpretor& ,
          if (wtyp == TopAbs_WIRE) {
            Spls.Add(TopoDS::Wire(W),TopoDS::Face(EF));
          }
-         else {
+         else if (wtyp == TopAbs_EDGE) {
            Spls.Add(TopoDS::Edge(W),TopoDS::Face(EF));
          }
+          else {
+           Spls.Add(TopoDS::Compound(W),TopoDS::Face(EF));
+          }
        }
        i++;
       }
@@ -2255,7 +2258,7 @@ void BRepTest::FeatureCommands (Draw_Interpretor& theCommands)
 
 
   theCommands.Add("splitshape",
-                 "splitshape result shape face wire/edge [wire/edge ...][face wire/edge [wire/edge...] ...] [@ edgeonshape edgeonwire [edgeonshape edgeonwire...]]",
+                 "splitshape result shape face wire/edge/compound [wire/edge/compound ...][face wire/edge/compound [wire/edge/compound...] ...] [@ edgeonshape edgeonwire [edgeonshape edgeonwire...]]",
                  __FILE__,SPLS,g);
 
 
index bf30bd0..999dc13 100755 (executable)
@@ -27,7 +27,8 @@ deferred class ProjectedWires from LocOpe inherits TShared from MMgt
 uses Face   from TopoDS,
      Wire   from TopoDS,
      Edge   from TopoDS,
-     Vertex from TopoDS
+     Vertex from TopoDS,
+     Shape  from TopoDS
 
 is
 
@@ -84,5 +85,9 @@ is
        returns Boolean from Standard
        is deferred;
 
+    IsFaceWithSection(me; aFace : Shape from TopoDS)
+       ---Purpose: tells is the face to be split by section or not
+       returns Boolean from Standard
+       is deferred;
 
 end ProjectedWires;
index 1a87b36..739b47f 100755 (executable)
@@ -92,6 +92,14 @@ is
               -- wire(s) of a sub-face of <F>
        is static;
     
+    Add(me: in out; Lwires: ListOfShape from TopTools;
+                   F: Face from TopoDS)
+       ---Purpose: Adds the list of wires <Lwires> on the face <F>.
+       raises NoSuchObject from Standard,
+              -- if <F> does not belong to the original shape.
+              ConstructionError from Standard
+       is static;
+    
 
     Shape(me)
        ---Purpose: Returns the "original" shape.
index 9fba291..907c755 100755 (executable)
 #include <TopTools_MapOfShape.hxx>
 #include <TopTools_DataMapOfShapeListOfShape.hxx>
 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
 #include <TopTools_MapIteratorOfMapOfShape.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopExp_Explorer.hxx>
 #include <BRep_Builder.hxx>
 #include <TopoDS_Vertex.hxx>
 #include <BRepLib_MakeFace.hxx>
+#include <BRepLib_MakeWire.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
 #include <BRep_Builder.hxx>
 
 #include <BRepClass_FaceExplorer.hxx>
@@ -67,6 +72,11 @@ static void ChoixUV(const TopoDS_Edge&,
                     gp_Vec2d&,
                     const Standard_Real tol);
 
+static TopoDS_Shape ChooseDirection(const TopoDS_Shape&,
+                                    const TopoDS_Vertex&,
+                                    const TopoDS_Face&,
+                                    const TopTools_ListOfShape&);
+
 inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2, 
                                const BRepAdaptor_Surface& theBAS)//const Standard_Real tol)
 {
@@ -220,6 +230,303 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
   }
 }
 
+//=======================================================================
+//function : Add
+//purpose  : adds the list of wires on the face <F>
+//=======================================================================
+
+void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
+                            const TopoDS_Face& F)
+{
+
+  if (myDone) {
+    Standard_ConstructionError::Raise();
+  }
+
+  TopTools_ListOfShape& lf = myMap(F);
+  if (lf.IsEmpty()) {
+    Rebuild(F);
+  }
+
+  // On cherche la face descendante de F qui continent le wire
+  lf = myMap(F);
+  TopTools_ListIteratorOfListOfShape itl(lf);
+  TopoDS_Vertex Vfirst,Vlast;
+
+  BRepTools::Update(F);
+
+  for (; itl.More(); itl.Next())
+  {
+    const TopoDS_Face& fac = TopoDS::Face(itl.Value());
+    Standard_Boolean AllWiresInside = Standard_True;
+    TopTools_ListIteratorOfListOfShape itwires(Lwires);
+    for (; itwires.More(); itwires.Next())
+    {
+      const TopoDS_Wire& aWire = TopoDS::Wire(itwires.Value());
+      if (!IsInside(fac, aWire))
+      {
+        AllWiresInside = Standard_False;
+        break;
+      }
+    }
+    if (AllWiresInside)
+      break;
+  }
+  if (!itl.More()) {
+    Standard_ConstructionError::Raise();
+  }
+
+  TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
+  FaceRef.Orientation(TopAbs_FORWARD);
+  lf.Remove(itl);
+
+  TopTools_ListOfShape NewWires;
+
+  TopTools_DataMapOfShapeInteger SectionsTimes;
+  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+    SectionsTimes.Bind(itl.Value(), 2);
+  
+  TopTools_ListOfShape BreakVertices;
+  TopTools_ListOfShape BreakOnWires;
+
+  TopTools_DataMapOfShapeShape VerWireMap;
+  Standard_Integer i;
+  TopExp_Explorer ExploF, ExploW;
+  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+  {
+    const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value());
+    TopoDS_Vertex Ver [2];
+    TopExp::Vertices(aSection, Ver[0], Ver[1]);
+    for (i = 0; i < 2; i++)
+    {
+      if (VerWireMap.IsBound(Ver[i]))
+        continue;
+      for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
+      {
+        const TopoDS_Shape& aWire = ExploF.Current();
+        TopoDS_Shape aVer;
+        for (ExploW.Init(aWire, TopAbs_VERTEX); ExploW.More(); ExploW.Next())
+        {
+          aVer = ExploW.Current();
+          if (aVer.IsSame(Ver[i]))
+            break;
+        }
+        if (aVer.IsSame(Ver[i]))
+        {
+          VerWireMap.Bind(aVer, aWire);
+          break;
+        }
+      }
+    }
+  }  
+  
+  TopTools_DataMapOfShapeListOfShape VerSecMap;
+  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+  {
+    const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value());
+    TopoDS_Vertex V1, V2;
+    TopExp::Vertices(aWire, V1, V2);
+    TopTools_ListOfShape LW1, LW2;
+    if (!VerSecMap.IsBound(V1))
+      VerSecMap.Bind(V1, LW1);
+    VerSecMap(V1).Append(aWire);
+    if (!VerSecMap.IsBound(V2))
+      VerSecMap.Bind(V2, LW2);
+    VerSecMap(V2).Append(aWire);
+  }
+
+  //TopTools_IndexedDataMapOfShapeShape InnerTouchingWiresOnVertex;
+  
+  TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
+  TopoDS_Wire CurWire = outerW;
+  BRepLib_MakeWire *MW;
+  MW = new BRepLib_MakeWire();
+  BRepTools_WireExplorer wexp(CurWire, FaceRef);
+  for (;;)
+  {
+    TopoDS_Vertex theStartVertex = wexp.CurrentVertex(), CurVertex;
+    TopoDS_Edge CurEdge = wexp.Current();
+    TopoDS_Edge LastEdge = CurEdge;
+    MW->Add(CurEdge);
+    TopoDS_Wire aSectionWire;
+    TopoDS_Vertex aBreakVertex;
+    wexp.Next();
+    if (!wexp.More())
+      wexp.Init(CurWire, FaceRef);
+    for (;;)
+    {
+      if (MW->Wire().Closed())
+        break;
+      CurVertex = wexp.CurrentVertex();
+      if (VerSecMap.IsBound(CurVertex))
+      {
+        TopoDS_Shape aLocalWire = ChooseDirection(LastEdge, CurVertex, FaceRef, VerSecMap(CurVertex));
+        aSectionWire = TopoDS::Wire(aLocalWire);
+        break;
+      }
+      CurEdge = wexp.Current();
+      MW->Add(CurEdge);
+      LastEdge = CurEdge;
+      wexp.Next();
+      if (!wexp.More())
+        wexp.Init(CurWire, FaceRef);
+    }
+    if (MW->Wire().Closed())
+    {
+      NewWires.Append(MW->Wire());
+      theStartVertex = TopoDS::Vertex(BreakVertices.First());
+      BreakVertices.RemoveFirst();
+      CurWire = TopoDS::Wire(BreakOnWires.First());
+      BreakOnWires.RemoveFirst();
+      wexp.Init(CurWire, FaceRef);
+      while (!wexp.CurrentVertex().IsSame(theStartVertex))
+        wexp.Next();
+      MW = new BRepLib_MakeWire();
+      continue;
+    }
+    aBreakVertex = CurVertex;
+    BreakVertices.Append(aBreakVertex);
+    BreakOnWires.Append(CurWire);
+    for (;;)
+    {
+      MW->Add(aSectionWire);
+      (SectionsTimes(aSectionWire))--;
+      if (SectionsTimes(aSectionWire) == 0)
+        SectionsTimes.UnBind(aSectionWire);
+      if (MW->Wire().Closed())
+      {
+        NewWires.Append(MW->Wire());
+        if (SectionsTimes.IsEmpty())
+          break;
+        theStartVertex = TopoDS::Vertex(BreakVertices.First());
+        BreakVertices.RemoveFirst();
+        CurWire = TopoDS::Wire(BreakOnWires.First());
+        BreakOnWires.RemoveFirst();
+        wexp.Init(CurWire, FaceRef);
+        while (!wexp.CurrentVertex().IsSame(theStartVertex))
+          wexp.Next();
+        MW = new BRepLib_MakeWire();
+        break;
+      }
+      else
+      {
+        TopoDS_Vertex V1, V2, aStartVertex;
+        TopExp::Vertices(aSectionWire, V1, V2);
+        aStartVertex = (V1.IsSame(aBreakVertex))? V2 : V1;
+        CurWire = TopoDS::Wire(VerWireMap(aStartVertex));
+        
+        wexp.Init(CurWire, FaceRef);
+        while (!wexp.CurrentVertex().IsSame(aStartVertex))
+          wexp.Next();
+            
+        const TopTools_ListOfShape& Lsections = VerSecMap(aStartVertex);
+        if (Lsections.Extent() == 1)
+          break;
+        
+        //else: choose the way
+        TopoDS_Wire NextSectionWire =
+          TopoDS::Wire((aSectionWire.IsSame(Lsections.First()))? Lsections.Last() : Lsections.First());
+        
+        Standard_Integer Times = 0;
+        TopTools_DataMapIteratorOfDataMapOfShapeShape itVW(VerWireMap);
+        for (; itVW.More(); itVW.Next())
+          if (itVW.Value().IsSame(CurWire))
+            Times++;
+        if (Times == 1) //it is inner touching wire
+        {
+          //InnerTouchingWiresOnVertex.Bind(aWire, aStartVertex);
+        }
+        else
+          {
+            //we have to choose the direction
+            TopoDS_Edge aStartEdge = wexp.Current();
+            TopTools_ListOfShape Ldirs;
+            Ldirs.Append(aStartEdge);
+            Ldirs.Append(NextSectionWire);
+            TopoDS_Shape theDirection = ChooseDirection(aSectionWire, aStartVertex, FaceRef, Ldirs);
+            if (theDirection.IsSame(aStartEdge))
+              break;
+          }
+        aSectionWire = NextSectionWire;
+        aBreakVertex = aStartVertex;
+      } //end of else (MW is not closed)
+    } //end of for (;;) (loop on section wires)
+    if (SectionsTimes.IsEmpty())
+      break;
+  } //end of global for (;;)
+
+  TopTools_ListOfShape NewFaces;
+  BRep_Builder BB;
+  for (itl.Initialize(NewWires); itl.More(); itl.Next())
+  {
+    TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
+    TopoDS_Face aNewFace = TopoDS::Face(aLocalFace);
+    aNewFace.Orientation(TopAbs_FORWARD);
+    BB.Add(aNewFace, itl.Value());
+    NewFaces.Append(aNewFace);
+  }
+
+  //Inserting holes
+  TopTools_ListOfShape Holes;
+  for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
+  {
+    const TopoDS_Shape& aWire = ExploF.Current();
+    ExploW.Init(aWire, TopAbs_EDGE);
+    TopoDS_Shape anEdge = ExploW.Current();
+    Standard_Boolean found = Standard_False;
+    for (itl.Initialize(NewWires); itl.More(); itl.Next())
+    {
+      const TopoDS_Shape& aNewWire = itl.Value();
+      for (ExploW.Init(aNewWire, TopAbs_EDGE); ExploW.More(); ExploW.Next())
+      {
+        if (anEdge.IsSame(ExploW.Current()))
+        {
+          found = Standard_True;
+          break;
+        }
+      }
+      if (found)
+        break;
+    }
+    if (!found)
+      Holes.Append(aWire);
+  }
+  TopTools_ListIteratorOfListOfShape itlNewF;
+  for (itl.Initialize(Holes); itl.More(); itl.Next())
+  {
+    const TopoDS_Wire& aHole = TopoDS::Wire(itl.Value());
+    for (itlNewF.Initialize(NewFaces); itlNewF.More(); itlNewF.Next())
+    {
+      TopoDS_Face& aNewFace = TopoDS::Face(itlNewF.Value());
+      if (IsInside(aNewFace, aHole))
+      {
+        BB.Add(aNewFace, aHole);
+        break;
+      }
+    }
+  }
+
+  //Update "myMap"
+  lf.Append(NewFaces);
+
+  //Update of descendants of wires
+  for (ExploF.Init(F, TopAbs_WIRE); ExploF.More(); ExploF.Next())
+  {
+    TopTools_ListOfShape& ls = myMap(ExploF.Current());
+    ls.Clear();
+  }
+  ///////////////////
+  
+  // JAG 10.11.95 Codage des regularites
+  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+    for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next())
+    {
+      const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current());
+      if (!BRep_Tool::HasContinuity(edg,F,F)) {
+        BB.Continuity(edg,F,F,GeomAbs_CN);
+      }
+    }
+}
 
 
 //=======================================================================
@@ -1047,7 +1354,7 @@ static Standard_Boolean IsInside(const TopoDS_Face& F,
     //  BRepClass_FaceClassifier classif(F,pt2d,Precision::PConfusion());
     //  return (classif.State() != TopAbs_OUT);
     BRepTopAdaptor_FClass2d classif(F,Precision::PConfusion());
-    Standard_Boolean stat = classif.Perform(pt2d);
+    TopAbs_State stat = classif.Perform(pt2d);
     //  return (classif.Perform(pt2d) != TopAbs_OUT);
     if(stat == TopAbs_OUT) return Standard_False;
 
@@ -1169,3 +1476,88 @@ static void ChoixUV(const TopoDS_Edge& Last,
   }
 
 }
+
+//=======================================================================
+//function : ChooseDirection
+//purpose  : 
+//=======================================================================
+
+static TopoDS_Shape ChooseDirection(const TopoDS_Shape& RefDir,
+                                    const TopoDS_Vertex& RefVertex,
+                                    const TopoDS_Face& theFace,
+                                    const TopTools_ListOfShape& Ldirs)
+{
+  TopExp_Explorer Explo(RefDir, TopAbs_EDGE);
+  TopoDS_Edge RefEdge;
+  TopoDS_Vertex V1, V2;
+  TopAbs_Orientation anOr;
+  for (; Explo.More(); Explo.Next())
+  {
+    RefEdge = TopoDS::Edge(Explo.Current());
+    TopExp::Vertices(RefEdge, V1, V2);
+    if (V1.IsSame(RefVertex))
+    {
+      anOr = TopAbs_REVERSED;
+      break;
+    }
+    else if (V2.IsSame(RefVertex))
+    {
+      anOr = TopAbs_FORWARD;
+      break;
+    }
+  }
+  
+  Standard_Real RefFirst, RefLast;
+  Handle(Geom2d_Curve) RefCurve = BRep_Tool::CurveOnSurface(RefEdge, theFace, RefFirst, RefLast);
+  gp_Pnt2d RefPnt;
+  gp_Vec2d RefVec;
+
+  //Standard_Real RefPar = (RefEdge.Orientation() == TopAbs_FORWARD)? RefLast : RefFirst;
+  Standard_Real RefPar = (anOr == TopAbs_FORWARD)? RefLast : RefFirst;
+  RefCurve->D1(RefPar, RefPnt, RefVec);
+  if (anOr == TopAbs_FORWARD)
+    RefVec.Reverse();
+
+  Handle(Geom2d_Curve) aCurve;
+  Standard_Real aFirst, aLast, aPar;
+  gp_Vec2d aVec;
+  Standard_Real MinAngle = RealLast(), anAngle;
+  TopoDS_Shape TargetDir;
+  TopTools_ListIteratorOfListOfShape itl(Ldirs);
+  for (; itl.More(); itl.Next())
+  {
+    const TopoDS_Shape& aShape = itl.Value();
+    TopoDS_Edge anEdge;
+    for (Explo.Init(aShape, TopAbs_EDGE); Explo.More(); Explo.Next())
+    {
+      anEdge = TopoDS::Edge(Explo.Current());
+      TopExp::Vertices(anEdge, V1, V2);
+      if (V1.IsSame(RefVertex))
+      {
+        anOr = TopAbs_FORWARD;
+        break;
+      }
+      else if (V2.IsSame(RefVertex))
+      {
+        anOr = TopAbs_REVERSED;
+        break;
+      }
+    }
+    aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, aFirst, aLast);
+    aPar = (anOr == TopAbs_FORWARD)? aFirst : aLast;
+    aCurve->D1(aPar, RefPnt, aVec);
+    if (anOr == TopAbs_REVERSED)
+      aVec.Reverse();
+    anAngle = aVec.Angle(RefVec);
+    if (anAngle < 0.)
+      anAngle += 2.*M_PI;
+
+    if (anAngle < MinAngle)
+    {
+      MinAngle = anAngle;
+      TargetDir = aShape;
+    }
+  }
+
+  return TargetDir;
+}
index cdbacff..9f23592 100755 (executable)
@@ -148,6 +148,7 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_ProjectedWires)& PW)
   TopoDS_Edge Ed;
   Standard_Real prm;
 
+  TopTools_MapOfShape theFacesWithSection;
   for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
     const TopoDS_Edge& edg = PW->Edge();
     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
@@ -169,8 +170,11 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_ProjectedWires)& PW)
     }
     else {
       TopoDS_Face fac = PW->OnFace();
-      if(!myMap.IsBound(fac)) continue; 
+      if(!myMap.IsBound(fac)) continue;
+      Standard_Boolean IsFaceWithSec = PW->IsFaceWithSection(fac);
       fac = TopoDS::Face(myMap(fac).First());
+      if (IsFaceWithSec)
+        theFacesWithSection.Add(fac);
       if (!mapFE.Contains(fac)) {
         TopTools_ListOfShape thelist;
        mapFE.Add(fac, thelist);
@@ -189,9 +193,11 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_ProjectedWires)& PW)
 //     RebuildWires(ledges);
     RebuildWires(ledges, PW);
 //  Modified by skv - Mon May 31 12:32:54 2004 OCC5865 End
-    for (itl.Initialize(ledges); itl.More(); itl.Next()) {
-      theCFace.Add(TopoDS::Wire(itl.Value()),fac);
-    }
+    if (theFacesWithSection.Contains(fac))
+      theCFace.Add(ledges, fac);
+    else
+      for (itl.Initialize(ledges); itl.More(); itl.Next())
+        theCFace.Add(TopoDS::Wire(itl.Value()),fac);
   }
 
 
index 4111f02..7dc9ba6 100755 (executable)
@@ -28,11 +28,13 @@ class WiresOnShape from LocOpe inherits ProjectedWires from LocOpe
 uses Shape               from TopoDS,
      Face                from TopoDS,
      Wire                from TopoDS,
+     Compound            from TopoDS,
      Edge                from TopoDS,
      Vertex              from TopoDS,
      DataMapOfShapeShape from TopTools,
 --     DataMapIteratorOfDataMapOfShapeShape from TopTools
-     IndexedDataMapOfShapeShape from TopTools
+     IndexedDataMapOfShapeShape from TopTools,
+     MapOfShape          from TopTools
 
 
 is
@@ -52,6 +54,10 @@ is
                     
        is static;
 
+    Bind(me: mutable; Comp: Compound from TopoDS;
+                      F:    Face from TopoDS)
+                    
+       is static;
 
     Bind(me: mutable; E: Edge from TopoDS;
                       F: Face from TopoDS)
@@ -129,12 +135,19 @@ is
        --          Else returns <Standard_False>.
        returns Boolean from Standard
        ;
+       
+    IsFaceWithSection(me; aFace : Shape from TopoDS)
+       ---Purpose: tells is the face to be split by section or not
+       ---C++: inline
+       returns Boolean from Standard
+       ;
 
 
 fields
 
     myShape : Shape                      from TopoDS;
     myMapEF : IndexedDataMapOfShapeShape from TopTools;
+    myFacesWithSection : MapOfShape      from TopTools;
     myMap   : DataMapOfShapeShape        from TopTools;
     myDone  : Boolean                    from Standard;
     myIndex : Integer                    from Standard;
index d6a4df8..4849783 100755 (executable)
 #include <TopoDS_Compound.hxx>
 #include <BRepLib.hxx>
 
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <BRepAdaptor_Curve2d.hxx>
+#include <Bnd_Box2d.hxx>
+#include <BndLib_Add2dCurve.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <BRepLib_MakeVertex.hxx>
+
+
 static Standard_Boolean Project(const TopoDS_Vertex&,
                                const TopoDS_Face&,
                                TopoDS_Edge&,
@@ -70,6 +78,11 @@ static void PutPCurves(const TopoDS_Edge&,
                       const TopoDS_Edge&,
                       const TopoDS_Shape&);
 
+static void FindInternalIntersections(const TopoDS_Edge&,
+                                      const TopoDS_Face&,
+                                      TopTools_IndexedDataMapOfShapeListOfShape&,
+                                      TopTools_DataMapOfShapeShape&,
+                                      TopTools_MapOfShape&);
 
 //=======================================================================
 //function : LocOpe_WiresOnShape
@@ -105,11 +118,24 @@ void LocOpe_WiresOnShape::Init(const TopoDS_Shape& S)
 void LocOpe_WiresOnShape::Bind(const TopoDS_Wire& W,
                               const TopoDS_Face& F)
 {
-  for (TopExp_Explorer exp(W,TopAbs_EDGE); exp.More(); exp.Next()) {
+  for (TopExp_Explorer exp(W, TopAbs_EDGE); exp.More(); exp.Next()) {
     Bind(TopoDS::Edge(exp.Current()),F);
   }
 }
 
+//=======================================================================
+//function : Bind
+//purpose  : 
+//=======================================================================
+
+void LocOpe_WiresOnShape::Bind(const TopoDS_Compound& Comp,
+                              const TopoDS_Face& F)
+{
+  for (TopExp_Explorer exp(Comp, TopAbs_EDGE); exp.More(); exp.Next()) {
+    Bind(TopoDS::Edge(exp.Current()),F);
+  }
+  myFacesWithSection.Add(F);
+}
 
 //=======================================================================
 //function : Bind
@@ -201,6 +227,38 @@ void LocOpe_WiresOnShape::BindAll()
     myMap.Bind(ite.Key(),ite.Value());
   }
 
+  TopTools_IndexedDataMapOfShapeListOfShape Splits;
+  Standard_Integer Ind;
+  for (Ind = 1; Ind <= myMapEF.Extent(); Ind++)
+  {
+    const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
+    const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
+    
+    PutPCurve(edg,fac);
+    Standard_Real pf, pl;
+    Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(edg, fac, pf, pl);
+    if (aPCurve.IsNull())
+      continue;
+
+    FindInternalIntersections(edg, fac, Splits, myMap, theMap);
+  }
+
+  for (Ind = 1; Ind <= Splits.Extent(); Ind++)
+  {
+    TopoDS_Shape anEdge = Splits.FindKey(Ind);
+    TopoDS_Shape aFace  = myMapEF.FindFromKey(anEdge);
+    //Remove "anEdge" from "myMapEF"
+    TopoDS_Shape LastEdge = myMapEF.FindKey(myMapEF.Extent());
+    TopoDS_Shape LastFace = myMapEF(myMapEF.Extent());
+    myMapEF.RemoveLast();
+    if (myMapEF.FindIndex(anEdge) != 0)
+      myMapEF.Substitute(myMapEF.FindIndex(anEdge), LastEdge, LastFace);
+    ////////////////////////////////
+    TopTools_ListIteratorOfListOfShape itl(Splits(Ind));
+    for (; itl.More(); itl.Next())
+      myMapEF.Add(itl.Value(), aFace);
+  }
+  
   // Il faut s`occuper maintenant des vertex "de changement de face", 
   // et des vertex "libres"
 //  TopTools_DataMapIteratorOfDataMapOfShapeShape ite2;
@@ -208,12 +266,12 @@ void LocOpe_WiresOnShape::BindAll()
 //  for (ite.Initialize(myMapEF); ite.More(); ite.Next()) {
 //    const TopoDS_Edge& edg = TopoDS::Edge(ite.Key());
 //    const TopoDS_Face& fac = TopoDS::Face(ite.Value());
-  for (Standard_Integer Ind = 1; Ind <= myMapEF.Extent(); Ind++) {
+  for (Ind = 1; Ind <= myMapEF.Extent(); Ind++) {
     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
     // JAG 02.02.96 : On verifie les pcurves...
 
-    PutPCurve(edg,fac);
+    //PutPCurve(edg,fac);
 
     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
@@ -1006,3 +1064,173 @@ void PutPCurves(const TopoDS_Edge& Efrom,
   }
 }
 
+//=======================================================================
+//function : FindInternalIntersections
+//purpose  : 
+//=======================================================================
+
+void FindInternalIntersections(const TopoDS_Edge& theEdge,
+                               const TopoDS_Face& theFace,
+                               TopTools_IndexedDataMapOfShapeListOfShape& Splits,
+                               TopTools_DataMapOfShapeShape& GlobalMap,
+                               TopTools_MapOfShape& theMap)
+{
+  Standard_Real TolExt = Precision::PConfusion();
+  Standard_Integer i, j, aNbExt;
+
+  TColStd_SequenceOfReal SplitPars;
+  
+  TopoDS_Vertex theVertices [2];
+  TopExp::Vertices(theEdge, theVertices[0], theVertices[1]);
+  if (theEdge.Orientation() == TopAbs_REVERSED)
+  {
+    theVertices[0].Reverse();
+    theVertices[1].Reverse();
+  }
+  gp_Pnt thePnt [2];
+  thePnt[0] = BRep_Tool::Pnt(theVertices[0]);
+  thePnt[1] = BRep_Tool::Pnt(theVertices[1]);
+  
+  BRepAdaptor_Curve2d thePCurve(theEdge, theFace);
+  Bnd_Box2d theBox;
+  BndLib_Add2dCurve::Add(thePCurve, BRep_Tool::Tolerance(theEdge), theBox);
+
+  Standard_Real thePar [2];
+  Standard_Real /*theFpar, theLpar,*/ aFpar, aLpar;
+  const Handle(Geom_Curve)& theCurve = BRep_Tool::Curve(theEdge, thePar[0], thePar[1]);
+  GeomAdaptor_Curve theGAcurve(theCurve, thePar[0], thePar[1]);
+  
+  TopExp_Explorer Explo(theFace, TopAbs_EDGE);
+  for (; Explo.More(); Explo.Next())
+  {
+    const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
+    BRepAdaptor_Curve2d aPCurve(anEdge, theFace);
+    Bnd_Box2d aBox;
+    BndLib_Add2dCurve::Add(aPCurve, BRep_Tool::Tolerance(anEdge), aBox);
+    if (theBox.IsOut(aBox))
+      continue;
+
+    const Handle(Geom_Curve)& aCurve   = BRep_Tool::Curve(anEdge, aFpar, aLpar);
+    GeomAdaptor_Curve aGAcurve(aCurve, aFpar, aLpar);
+    Extrema_ExtCC anExtrema(theGAcurve, aGAcurve, TolExt, TolExt);
+
+    if (!anExtrema.IsDone())
+      continue;
+    if (anExtrema.IsParallel())
+      continue;
+
+    aNbExt = anExtrema.NbExt();
+    Standard_Real MaxTol = Max(BRep_Tool::Tolerance(theEdge), BRep_Tool::Tolerance(anEdge));
+    for (i = 1; i <= aNbExt; i++)
+    {
+      Standard_Real aDist = Sqrt(anExtrema.SquareDistance(i));
+      if (aDist > MaxTol)
+        continue;
+
+      Extrema_POnCurv aPOnC1, aPOnC2;
+      anExtrema.Points(i, aPOnC1, aPOnC2);
+      Standard_Real theIntPar = aPOnC1.Parameter();
+      Standard_Real anIntPar = aPOnC2.Parameter();
+      Standard_Boolean IntersFound = Standard_False;
+      for (j = 0; j < 2; j++) //try to find intersection on an extremity of "theEdge"
+      {
+        if (Abs(theIntPar - thePar[j]) <= Precision::PConfusion() &&
+            aDist <= Precision::Confusion())
+        {
+          theMap.Add(theVertices[j]);
+          TopExp_Explorer exp2(anEdge, TopAbs_VERTEX);
+          for (; exp2.More(); exp2.Next())
+          {
+            const TopoDS_Vertex& aVertex = TopoDS::Vertex(exp2.Current());
+            if (aVertex.IsSame(theVertices[j]))
+            {
+              IntersFound = Standard_True;
+              break;
+            }
+            if (BRepTools::Compare(theVertices[j], aVertex))
+            {
+              GlobalMap.Bind(theVertices[j], aVertex);
+              IntersFound = Standard_True;
+              break;
+            }
+          }
+          if (!IntersFound)
+          {
+            GlobalMap.Bind(theVertices[j], anEdge);
+            IntersFound = Standard_True;
+            break;
+          }
+        }
+      }
+      if (!IntersFound) //intersection is inside "theEdge" => split
+      {
+        gp_Pnt aPoint = aCurve->Value(anIntPar);
+        if (aPoint.Distance(thePnt[0]) > BRep_Tool::Tolerance(theVertices[0]) &&
+            aPoint.Distance(thePnt[1]) > BRep_Tool::Tolerance(theVertices[1]))
+          SplitPars.Append(theIntPar);
+      }
+    }
+  }
+
+  if (SplitPars.IsEmpty())
+    return;
+  
+  //Sort
+  for (i = 1; i < SplitPars.Length(); i++)
+    for (j = i+1; j <= SplitPars.Length(); j++)
+      if (SplitPars(i) > SplitPars(j))
+      {
+        Standard_Real Tmp = SplitPars(i);
+        SplitPars(i) = SplitPars(j);
+        SplitPars(j) = Tmp;
+      }
+
+  //Remove repeating points
+  i = 1;
+  while (i < SplitPars.Length())
+  {
+    gp_Pnt Pnt1 = theCurve->Value(SplitPars(i));
+    gp_Pnt Pnt2 = theCurve->Value(SplitPars(i+1));
+    if (Pnt1.Distance(Pnt2) <= Precision::Confusion())
+      SplitPars.Remove(i+1);
+    else
+      i++;
+  }
+
+  //Split
+  TopTools_ListOfShape NewEdges;
+  BRep_Builder BB;
+  //theVertices[0].Orientation(TopAbs_FORWARD);
+  //theVertices[1].Orientation(TopAbs_REVERSED);
+  TopoDS_Vertex FirstVertex = theVertices[0], LastVertex;
+  Standard_Real FirstPar = thePar[0], LastPar;
+  for (i = 1; i <= SplitPars.Length()+1; i++)
+  {
+    FirstVertex.Orientation(TopAbs_FORWARD);
+    if (i <= SplitPars.Length())
+    {
+      LastPar = SplitPars(i);
+      gp_Pnt LastPoint = theCurve->Value(LastPar);
+      LastVertex = BRepLib_MakeVertex(LastPoint);
+    }
+    else
+    {
+      LastPar = thePar[1];
+      LastVertex = theVertices[1];
+    }
+    LastVertex.Orientation(TopAbs_REVERSED);
+    
+    TopoDS_Shape aLocalShape = theEdge.EmptyCopied();
+    TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
+    BB.Range(NewEdge, FirstPar, LastPar);
+    BB.Add(NewEdge, FirstVertex);
+    BB.Add(NewEdge, LastVertex);
+
+    NewEdges.Append(NewEdge);
+    FirstVertex = LastVertex;
+    FirstPar = LastPar;
+  }
+
+  if (!NewEdges.IsEmpty())
+    Splits.Add(theEdge, NewEdges);
+}
index 340455a..f334fae 100755 (executable)
@@ -29,3 +29,13 @@ inline Standard_Boolean LocOpe_WiresOnShape::IsDone() const
 {
   return myDone;
 }
+
+//=======================================================================
+//function : IsFaceWithSection
+//purpose  : 
+//=======================================================================
+
+inline Standard_Boolean LocOpe_WiresOnShape::IsFaceWithSection(const TopoDS_Shape& aFace) const
+{
+  return (myFacesWithSection.Contains(aFace));
+}