0027151: Exception is raised during performing command "splitshape" in the Test Harness
authorgka <gka@opencascade.com>
Wed, 2 Mar 2016 08:01:02 +0000 (11:01 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 8 Apr 2016 08:42:11 +0000 (11:42 +0300)
Added protection for cases of the overlapped edges.
Returning value for methods in the LocOpe_SplitShape::AddOpenWire(), LocOpe_SplitShape::AddClosedWire() are modified from void to boolean in order to avoid raising exceptions.
To avoid regression for test case modalg_5 bug25243 tolerance of vertices of the degenerated edges are increased to value of tolerance of the splitting vertex for case when splitting vertex was projected on  the degenerated edge.

src/LocOpe/LocOpe_SplitShape.cxx
src/LocOpe/LocOpe_SplitShape.hxx
src/LocOpe/LocOpe_Spliter.cxx
src/LocOpe/LocOpe_WiresOnShape.cxx
tests/bugs/modalg_6/bug27151 [new file with mode: 0644]

index 54a44a1..53da2ab 100644 (file)
@@ -66,11 +66,11 @@ static Standard_Boolean IsInside(const TopoDS_Face&,
 
 static void GetDirection(const TopoDS_Edge&,
                          const TopoDS_Face&,
-                         Standard_Real&,
                          gp_Pnt2d&,
-                         gp_Vec2d&);
+                         gp_Vec2d&, 
+                         Standard_Boolean isFirstEnd);
 
-static void ChoixUV(const TopoDS_Edge&,
+static Standard_Boolean ChoixUV(const TopoDS_Edge&,
                     const TopoDS_Face&,
                     const TopTools_IndexedMapOfShape&,
                     TopoDS_Edge&,
@@ -86,9 +86,6 @@ static TopoDS_Shape ChooseDirection(const TopoDS_Shape&,
 inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2, 
                                const BRepAdaptor_Surface& theBAS)//const Standard_Real tol)
 {
-  //  Standard_Real tol = Precision::Confusion();
-  //  return P1.SquareDistance(P2) < 10*tol;
-  //gka
   Standard_Boolean isSame = Standard_True;
   if(theBAS.IsUPeriodic())
     isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5);
@@ -159,7 +156,7 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
                             const TopoDS_Edge& E)
 {
   if (!CanSplit(E)) {
-    Standard_ConstructionError::Raise();
+    return;
   }
 
   BRep_Builder B;
@@ -169,22 +166,31 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
   }
   TopTools_ListIteratorOfListOfShape itl(le);
   Standard_Real f,l;
-
+  TopTools_ListOfShape aNewList;
   for (; itl.More(); itl.Next()) {
     const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
     BRep_Tool::Range(edg,f,l);
-    if (P>f && P <l) {
+    if (P > f + Precision::PConfusion() && P < l - Precision::PConfusion()) {
       break;
+     
     }
+    aNewList.Append(edg);
   }
   if (!itl.More()) {
-    Standard_ConstructionError::Raise();
+    return;
   }
   TopoDS_Edge edg = TopoDS::Edge(itl.Value());
   le.Remove(itl);
   if (V.Orientation() == TopAbs_FORWARD ||
     V.Orientation() == TopAbs_REVERSED) {
 
+      edg.Orientation(TopAbs_FORWARD);
+      TopoDS_Vertex aCurV1, aCurV2;
+      TopExp::Vertices(edg, aCurV1, aCurV2);
+      Standard_Real aPar1 = BRep_Tool::Parameter(aCurV1,edg);
+      
+      Standard_Real aPar2 = BRep_Tool::Parameter(aCurV2,edg);
+
       TopoDS_Shape aLocalShape = edg.EmptyCopied();
       TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
       aLocalShape = edg.EmptyCopied();
@@ -194,37 +200,50 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
       E1.Orientation(TopAbs_FORWARD);
       E2.Orientation(TopAbs_FORWARD);
       TopoDS_Vertex newVtx = V;
+      Standard_Real aTolSplitV = BRep_Tool::Tolerance(V);
+      
+      aCurV1.Orientation(TopAbs_FORWARD);
+     
+      B.Add(E1,aCurV1);
+      //for degenerated edges tolerance of vertices should be set to maximal value
+      //from tolerance of the vertex of the edge and tolerance of splitting vertex
+      Standard_Real aTolV1 = ( BRep_Tool::Degenerated(edg) ?
+        Max(BRep_Tool::Tolerance(aCurV1), aTolSplitV) : BRep_Tool::Tolerance(aCurV1));
+     
+      B.UpdateVertex(aCurV1,aPar1,E1, aTolV1);
       newVtx.Orientation(TopAbs_REVERSED);
       B.Add(E1,newVtx);
       B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V));
       newVtx.Orientation(TopAbs_FORWARD);
       B.Add(E2,newVtx);
       B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V));
-      edg.Orientation(TopAbs_FORWARD);
-      TopExp_Explorer exp;
-      for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
-        //    for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
-        const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
-        f = BRep_Tool::Parameter(vtx,edg);
-        if (f < P) {
-          B.Add(E1,vtx);
-          B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
-        }
-        else {
-          B.Add(E2,vtx);
-          B.UpdateVertex(vtx,f,E2,BRep_Tool::Tolerance(vtx));
-        }
+      
+      aCurV2.Orientation(TopAbs_REVERSED);
+      B.Add(E2,aCurV2);
+
+      //for degenerated edges tolerance of vertices should be set to maximal value
+      //from tolerance of the vertex of the edge and tolerance of splitting vertex
+      Standard_Real aTolV2 = ( BRep_Tool::Degenerated(edg) ? aTolV1 : BRep_Tool::Tolerance(aCurV2));
+      B.UpdateVertex(aCurV2,aPar2,E2,aTolV2);
+      
+      aNewList.Append(E1);
+      aNewList.Append(E2);
+      for (; itl.More(); itl.Next()) 
+      {
+        const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
+        aNewList.Append(edg);
       }
-      le.Append(E1);
-      le.Append(E2);
+      myMap.UnBind(E);
+      myMap.Bind(E, aNewList);
+
   }
   else {
     TopoDS_Shape aLocalShape = edg.EmptyCopied();
     TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
-    //    TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
+   
     TopExp_Explorer exp;
     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
-      //    for (TopExp_Explorer exp(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
+     
       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
       f = BRep_Tool::Parameter(vtx,edg);
       B.Add(E1,vtx);
@@ -241,12 +260,12 @@ void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
 //purpose  : adds the list of wires on the face <F>
 //=======================================================================
 
-void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
+Standard_Boolean LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
                             const TopoDS_Face& F)
 {
 
   if (myDone) {
-    Standard_ConstructionError::Raise();
+    return Standard_False;
   }
 
   TopTools_ListOfShape& lf = myMap(F);
@@ -261,25 +280,25 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
 
   BRepTools::Update(F);
 
+  TopTools_ListOfShape aLInside;
   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))
+      if (IsInside(fac, aWire))
       {
-        AllWiresInside = Standard_False;
-        break;
+        aLInside.Append(aWire);
+        
       }
     }
-    if (AllWiresInside)
+    if(aLInside.Extent())
       break;
   }
-  if (!itl.More()) {
-    Standard_ConstructionError::Raise();
+  if (!aLInside.Extent() || !itl.More()) {
+    return Standard_False;
   }
 
   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
@@ -289,7 +308,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
   TopTools_ListOfShape NewWires;
 
   TopTools_DataMapOfShapeInteger SectionsTimes;
-  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+  for (itl.Initialize(aLInside); itl.More(); itl.Next())
     SectionsTimes.Bind(itl.Value(), 2);
   
   TopTools_ListOfShape BreakVertices;
@@ -298,7 +317,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
   TopTools_DataMapOfShapeShape VerWireMap;
   Standard_Integer i;
   TopExp_Explorer ExploF, ExploW;
-  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+  for (itl.Initialize(aLInside); itl.More(); itl.Next())
   {
     const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value());
     TopoDS_Vertex Ver [2];
@@ -327,7 +346,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
   }  
   
   TopTools_DataMapOfShapeListOfShape VerSecMap;
-  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+  for (itl.Initialize(aLInside); itl.More(); itl.Next())
   {
     const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value());
     TopoDS_Vertex V1, V2;
@@ -524,7 +543,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
   ///////////////////
   
   // JAG 10.11.95 Codage des regularites
-  for (itl.Initialize(Lwires); itl.More(); itl.Next())
+  for (itl.Initialize(aLInside); itl.More(); itl.Next())
     for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next())
     {
       const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current());
@@ -532,6 +551,7 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
         BB.Continuity(edg,F,F,GeomAbs_CN);
       }
     }
+  return Standard_True;
 }
 
 
@@ -540,12 +560,12 @@ void LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
 //purpose  : 
 //=======================================================================
 
-void LocOpe_SplitShape::Add(const TopoDS_Wire& W,
+Standard_Boolean LocOpe_SplitShape::Add(const TopoDS_Wire& W,
                             const TopoDS_Face& F)
 {
 
   if (myDone) {
-    Standard_ConstructionError::Raise();
+    return Standard_False;
   }
 
 
@@ -557,16 +577,18 @@ void LocOpe_SplitShape::Add(const TopoDS_Wire& W,
   try {
     OCC_CATCH_SIGNALS
     if (!LocOpe::Closed(W,F)) {
-      AddOpenWire(W,F);
+      if(!AddOpenWire(W,F))
+        return Standard_False;
     }
     else {
-      AddClosedWire(W,F);
+      if(!AddClosedWire(W,F))
+        return Standard_False;
     }
   } catch (Standard_Failure ) {
 #ifdef OCCT_DEBUG
     cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <<endl;
 #endif
-    return;
+    return Standard_False;
   }
   // JAG 10.11.95 Codage des regularites
   BRep_Builder B;
@@ -576,6 +598,7 @@ void LocOpe_SplitShape::Add(const TopoDS_Wire& W,
       B.Continuity(edg,F,F,GeomAbs_CN);
     }
   }
+  return Standard_True;
 }
 
 
@@ -585,7 +608,7 @@ void LocOpe_SplitShape::Add(const TopoDS_Wire& W,
 //purpose  : 
 //=======================================================================
 
-void LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
+Standard_Boolean LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
                                       const TopoDS_Face& F)
 {
   TopExp_Explorer exp;
@@ -596,19 +619,14 @@ void LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
   TopoDS_Wire outerW;
   for (; itl.More(); itl.Next()) {
     const TopoDS_Face& fac = TopoDS::Face(itl.Value());
-    /*
-    outerW = BRepTools::OuterWire(fac);
-    if (IsInside(F,W,outerW)) {
-    break;
-    }
-    */
+
     if (IsInside(fac,W)) {
       break;
     }
 
   }
   if (!itl.More()) {
-    Standard_ConstructionError::Raise();
+    return Standard_False;
   }
 
   BRep_Builder B;
@@ -658,7 +676,7 @@ void LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
   B.Add(newRef,W.Oriented(TopAbs::Reverse(orWire)));
   lf.Append(newRef);
   lf.Append(newFace);
-
+  return Standard_True;
 }
 
 
@@ -667,7 +685,7 @@ void LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
 //purpose  : 
 //=======================================================================
 
-void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
+Standard_Boolean LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
                                     const TopoDS_Face& F)
 {
   // On cherche la face descendante de F qui continent le wire
@@ -723,7 +741,7 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
     }
   }
   if (!itl.More()) {
-    Standard_ConstructionError::Raise();
+    return Standard_False;
   }
 
   TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
@@ -820,27 +838,8 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
       }
     }
     aLocalFace  = FaceRef.Oriented(wfirst.Orientation());
-    C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
-    Standard_Real dpar = (l - f)*0.01;
-    if (LastEdge.Orientation() == TopAbs_FORWARD) {
-      C2d->D1(l,plast,dlast);
-      if (dlast.Magnitude() < gp::Resolution())
-      {
-        gp_Pnt2d PrevPnt = C2d->Value(l - dpar);
-        dlast.SetXY(plast.XY() - PrevPnt.XY());
-      }
-    }
-    else {
-      C2d->D1(f,plast,dlast);
-      if (dlast.Magnitude() < gp::Resolution())
-      {
-        gp_Pnt2d NextPnt = C2d->Value(f + dpar);
-        dlast.SetXY(NextPnt.XY() - plast.XY());
-      }
-      dlast.Reverse();
-    }
-
+    GetDirection(LastEdge, TopoDS::Face(aLocalFace),plast , dlast, Standard_False);
+   
     Standard_Boolean cond;
 
     if(IsPeriodic) {
@@ -861,12 +860,10 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
 
         orient = edg.Orientation();
         TopExp::Vertices(edg,vdeb,vfin);
-        if (orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) {
-          PossE.Add(edg.Oriented(orient));
-        }
-        else if (orient == TopAbs_REVERSED && Vlast.IsSame(vfin)) {
-          PossE.Add(edg.Oriented(orient));
-        }
+        
+        if ((orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) || 
+          (orient == TopAbs_REVERSED && Vlast.IsSame(vfin))) 
+          PossE.Add(edg);
       }
       nbPoss = PossE.Extent();
       if (nbPoss == 0)
@@ -878,41 +875,24 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
       if (nbPoss == 1) {
         aNextEdge = TopoDS::Edge (PossE.FindKey (1));
         TopoDS_Shape aLocalFaceTemp  = FaceRef.Oriented(wfirst.Orientation());
-        C2d = BRep_Tool::CurveOnSurface(aNextEdge,
-                                        TopoDS::Face(aLocalFaceTemp), f, l);
-        Standard_Real dparnew = (l - f)*0.01;
-
-        if (aNextEdge.Orientation() == TopAbs_FORWARD) {
-          C2d->D1(l,plast,dlast);
-          if (dlast.Magnitude() < gp::Resolution())
-          {
-            gp_Pnt2d PrevPnt = C2d->Value(l - dparnew);
-            dlast.SetXY(plast.XY() - PrevPnt.XY());
-          }
-        }
-        else {
-          C2d->D1(f,plast,dlast);
-          if (dlast.Magnitude() < gp::Resolution())
-          {
-            gp_Pnt2d NextPnt = C2d->Value(f + dparnew);
-            dlast.SetXY(NextPnt.XY() - plast.XY());
-          }
-          dlast.Reverse();
-        }
+        GetDirection(aNextEdge, TopoDS::Face(aLocalFaceTemp),plast , dlast, Standard_False);
+       
       }
       else if (nbPoss > 1) {
         // Faire choix en U,V...
         TopoDS_Shape aLocalFaceTemp  = FaceRef.Oriented(wfirst.Orientation());
         
-        ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE,
-                aNextEdge, plast, dlast, toll);
+        if(!ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE,
+                aNextEdge, plast, dlast, toll))
+                return Standard_False;
+
       }
 
       if (nbPoss >= 1) {
         if (aNextEdge.IsNull())
         {
           // loop is not closed. Split is not possible
-          Standard_ConstructionError::Raise("Split is not possible: split loop is not closed"); 
+          return Standard_False;
         }
 
         if (MapE.Contains(aNextEdge)) 
@@ -935,7 +915,7 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
       //MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur
       else{
         cout<<"erreur Spliter : pas de chainage du wire"<<endl;
-        Standard_ConstructionError::Raise();        
+        return Standard_False;
       }
       //fin MODIF.
       
@@ -963,10 +943,7 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
     // modifs JAG 97.05.28
 
     B.Add(newF1,newW1);
-    //BRepTools::Write(newF1, "k:/queries/WrongBOP/NewF1.brep");
     B.Add(newF2,newW2);
-    //BRepTools::Write(newF2, "k:/queries/WrongBOP/NewF2.brep");
-    
     for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); exp.More(); exp.Next()) {
       const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
       if (!wir.IsSame(wfirst)) {
@@ -1086,6 +1063,7 @@ void LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
       
     }
   }
+  return Standard_True;
 }
 
 
@@ -1368,44 +1346,35 @@ static Standard_Boolean IsInside(const TopoDS_Face& F,
 //=======================================================================
 static void GetDirection(const TopoDS_Edge& theEdge,
                          const TopoDS_Face& theFace,
-                         Standard_Real& theTol,
                          gp_Pnt2d& thePnt,
-                         gp_Vec2d& theDir)
+                         gp_Vec2d& theDir,
+                         Standard_Boolean isFirstEnd)
 {
   Standard_Real aFirst, aLast;
   Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface (theEdge, theFace, aFirst, aLast);
 
   TopAbs_Orientation anOr = theEdge.Orientation();
   TopoDS_Vertex aVtx;
-  if (anOr == TopAbs_FORWARD)
+  Standard_Boolean takeFirst = ((anOr == TopAbs_FORWARD && isFirstEnd) ||
+    (anOr == TopAbs_REVERSED && !isFirstEnd));
+  Standard_Real dpar = (aLast - aFirst)*0.01;
+  gp_Pnt2d aP2d;
+  if (takeFirst)
   {
-    aVtx = TopExp::FirstVertex (theEdge);
     aC2d->D0 (aFirst, thePnt);
+    gp_Pnt2d aNextPnt = aC2d->Value(aFirst + dpar);
+    theDir = gp_Vec2d(thePnt, aNextPnt);
   }
-  else
-  {
-    aVtx = TopExp::LastVertex (theEdge);
-    aC2d->D0 (aLast, thePnt);
-  }
-
-  BRepAdaptor_Surface aSurf (theFace, Standard_False);
-  theTol = BRep_Tool::Tolerance (aVtx);
-  Standard_Real aTol = Max (aSurf.UResolution (theTol), aSurf.VResolution (theTol));
-  aTol = Min (aTol, (aLast - aFirst)*0.1);
-
-  gp_Pnt2d aP2d;
 
-  if (anOr == TopAbs_FORWARD)
-  {
-      aFirst += aTol;
-      aC2d->D0 (aFirst, aP2d);
-  }
   else
   {
-      aLast -= aTol;
-      aC2d->D0 (aLast, aP2d);
+    aC2d->D0 (aLast, thePnt);
+    gp_Pnt2d aPrevPnt = aC2d->Value(aLast - dpar);
+    theDir = gp_Vec2d( aPrevPnt, thePnt );
   }
-  theDir = gp_Vec2d (thePnt, aP2d);
+  if(anOr == TopAbs_REVERSED)
+    theDir.Reverse();
 }
 
 //=======================================================================
@@ -1413,7 +1382,7 @@ static void GetDirection(const TopoDS_Edge& theEdge,
 //purpose  : 
 //=======================================================================
 
-static void ChoixUV(const TopoDS_Edge& Last,
+Standard_Boolean ChoixUV(const TopoDS_Edge& Last,
                     const TopoDS_Face& F,
                     const TopTools_IndexedMapOfShape& Poss,
                     TopoDS_Edge& theResEdge,
@@ -1421,8 +1390,6 @@ static void ChoixUV(const TopoDS_Edge& Last,
                     gp_Vec2d& dlst,
                     const Standard_Real toll)
 {
-
-  Standard_Real f,l;
   gp_Pnt2d p2d;
   gp_Vec2d v2d;
   gp_Pnt aPCur, aPlst;
@@ -1435,15 +1402,19 @@ static void ChoixUV(const TopoDS_Edge& Last,
   gp_Dir2d ref2d(dlst);
 
   Handle(Geom2d_Curve) C2d;
-  Standard_Real dpar;
+  
 
   Standard_Integer index = 0, imin=0;
   Standard_Real  angmax = -M_PI, dist, ang;
-
-
+  
   for (index = 1; index <= Poss.Extent(); index++) {
     TopoDS_Edge anEdge = TopoDS::Edge (Poss.FindKey (index));
-    GetDirection (anEdge, F, tol, p2d, v2d);
+    
+    TopoDS_Vertex aVF = TopExp::FirstVertex(anEdge, Standard_True);
+               if( aVF.IsNull())
+      return 0;
+    tol = BRep_Tool::Tolerance(aVF);
+    GetDirection (anEdge, F, p2d, v2d, Standard_True);
 
     surf.D0 (p2d.X(), p2d.Y(), aPCur);
 
@@ -1467,29 +1438,10 @@ static void ChoixUV(const TopoDS_Edge& Last,
   if (imin)
   {
     theResEdge = TopoDS::Edge (Poss.FindKey (imin));
-    C2d = BRep_Tool::CurveOnSurface (theResEdge, F, f, l);
-    dpar = (l - f)*0.01;
-    if (theResEdge.Orientation() == TopAbs_FORWARD)
-    {
-      C2d->D1 (l, plst, dlst);
-      if (dlst.Magnitude() < gp::Resolution())
-      {
-        gp_Pnt2d PrevPnt = C2d->Value(l - dpar);
-        dlst.SetXY(plst.XY() - PrevPnt.XY());
-      }
-    }
-    else
-    {
-      C2d->D1 (f, plst, dlst);
-      if (dlst.Magnitude() < gp::Resolution())
-      {
-        gp_Pnt2d NextPnt = C2d->Value(f + dpar);
-        dlst.SetXY(NextPnt.XY() - plst.XY());
-      }
-      dlst.Reverse();
-    }
+    GetDirection (theResEdge, F, plst, dlst, Standard_False);
   }
 
+  return (imin);
 }
 
 //=======================================================================
index 5e55810..df6a6e3 100644 (file)
@@ -65,10 +65,10 @@ public:
   Standard_EXPORT void Add (const TopoDS_Vertex& V, const Standard_Real P, const TopoDS_Edge& E);
   
   //! Adds the wire <W> on the face <F>.
-  Standard_EXPORT void Add (const TopoDS_Wire& W, const TopoDS_Face& F);
+  Standard_EXPORT Standard_Boolean Add (const TopoDS_Wire& W, const TopoDS_Face& F);
   
   //! Adds the list of wires <Lwires> on the face <F>.
-  Standard_EXPORT void Add (const TopTools_ListOfShape& Lwires, const TopoDS_Face& F);
+  Standard_EXPORT Standard_Boolean Add (const TopTools_ListOfShape& Lwires, const TopoDS_Face& F);
   
   //! Returns the "original" shape.
     const TopoDS_Shape& Shape() const;
@@ -95,9 +95,9 @@ protected:
 private:
 
   
-  Standard_EXPORT void AddOpenWire (const TopoDS_Wire& W, const TopoDS_Face& F);
+  Standard_EXPORT Standard_Boolean AddOpenWire (const TopoDS_Wire& W, const TopoDS_Face& F);
   
-  Standard_EXPORT void AddClosedWire (const TopoDS_Wire& W, const TopoDS_Face& F);
+  Standard_EXPORT Standard_Boolean AddClosedWire (const TopoDS_Wire& W, const TopoDS_Face& F);
   
   Standard_EXPORT void Put (const TopoDS_Shape& S);
   
index 4fdd222..d7080b1 100644 (file)
@@ -143,7 +143,7 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
 
   TopTools_MapOfShape theFacesWithSection;
   for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
-    const TopoDS_Edge& edg = PW->Edge();
+    TopoDS_Edge edg = PW->Edge();
     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
       if (!mapV.Contains(vtx)) {
@@ -286,7 +286,7 @@ void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
       TopoDS_Shape ebase = lsubs.First();
       lsubs.Clear();
       lsubs.Append(e1.Oriented(ebase.Orientation()));
-      theSubs.Substitute(ebase.Oriented(TopAbs_FORWARD),lsubs);
+      theSubs.Substitute(ebase,lsubs);
     }
     else {
 #ifdef OCCT_DEBUG
index b538a48..e1a5648 100644 (file)
@@ -84,9 +84,7 @@ static void PutPCurves(const TopoDS_Edge&,
 
 static void FindInternalIntersections(const TopoDS_Edge&,
                                       const TopoDS_Face&,
-                                      TopTools_IndexedDataMapOfShapeListOfShape&,
-                                      TopTools_DataMapOfShapeShape&,
-                                      TopTools_MapOfShape&);
+                                      TopTools_IndexedDataMapOfShapeListOfShape&);
 
 //=======================================================================
 //function : LocOpe_WiresOnShape
@@ -243,7 +241,7 @@ void LocOpe_WiresOnShape::BindAll()
       continue;
 
     if (myCheckInterior)
-      FindInternalIntersections(edg, fac, Splits, myMap, theMap);
+      FindInternalIntersections(edg, fac, Splits);
   }
 
   for (Ind = 1; Ind <= Splits.Extent(); Ind++)
@@ -262,13 +260,7 @@ void LocOpe_WiresOnShape::BindAll()
       myMapEF.Add(itl.Value(), aFace);
   }
   
-  // Il faut s`occuper maintenant des vertex "de changement de face", 
-  // et des vertex "libres"
-//  TopTools_DataMapIteratorOfDataMapOfShapeShape ite2;
-
-//  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 (Ind = 1; Ind <= myMapEF.Extent(); Ind++) {
     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
@@ -281,24 +273,27 @@ void LocOpe_WiresOnShape::BindAll()
       if (theMap.Contains(vtx)) {
        continue;
       }
-      ////
+      
       Standard_Real vtx_param = BRep_Tool::Parameter(vtx, edg);
       BRepAdaptor_Curve2d BAcurve2d(edg, fac);
       gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
-      ////
+
       TopoDS_Edge Epro;
       Standard_Real prm = 0.;
       Standard_Boolean ok = Project(vtx, p2d, fac, Epro, prm);
       if (ok) {
+       
        for (exp2.Init(Epro,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
          const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
          if (vtx2.IsSame(vtx)) {
            break;
          }
          else if (BRepTools::Compare(vtx,vtx2)) {
+            Standard_Real aF1, aL1;
+            BRep_Tool::Range(Epro, fac, aF1, aL1);
             if (!BRep_Tool::Degenerated(Epro) ||
-                Abs(prm-BAcurve2d.FirstParameter()) <= Precision::PConfusion() ||
-                Abs(prm-BAcurve2d.LastParameter())  <= Precision::PConfusion())
+                Abs(prm-aF1) <= Precision::PConfusion() ||
+                Abs(prm-aL1)  <= Precision::PConfusion())
             {
               myMap.Bind(vtx,vtx2);
               break;
@@ -460,13 +455,24 @@ Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
   }
   
   Ed = TopoDS::Edge(myMap(V));
-  TopoDS_Face theFace = TopoDS::Face(myMapEF.FindFromKey(EdgeFrom));
-  ////
-  Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom);
-  BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, theFace);
-  gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
-  ////
-  prm = Project(V, p2d, Ed, theFace);
+  if(!myMapEF.Contains(EdgeFrom))
+    return Standard_False;
+
+  TopoDS_Shape aShape = myMapEF.FindFromKey(EdgeFrom);
+  if(  aShape.ShapeType() == TopAbs_FACE)
+  {
+
+    TopoDS_Face aFace = TopoDS::Face(aShape);
+    Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom);
+    BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, aFace);
+    gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
+
+
+    prm = Project(V, p2d, Ed, aFace);
+  }
+  else
+    prm = Project( V, TopoDS::Edge(Ed));
+       
   return Standard_True;
 }
 
@@ -509,12 +515,33 @@ Standard_Boolean Project(const TopoDS_Vertex& V,
 
   if(theEdge.IsNull())
     return Standard_False;
-
-  Standard_Real ttol = BRep_Tool::Tolerance(V) + BRep_Tool::Tolerance(theEdge);
-  if (dmin <= ttol) {
+  //compute distance in 3D space
+
+  Handle(Geom2d_Curve) aCrvBound = BRep_Tool::CurveOnSurface(theEdge, F, f, l);
+  gp_Pnt2d aPBound2d;
+  aCrvBound->D0(param,aPBound2d);
+  gp_Pnt aPBound;
+  Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
+  aSurf->D0(aPBound2d.X(), aPBound2d.Y(), aPBound);
+  
+  //point of vertex computed by pcurve of the splitting edge
+  gp_Pnt aPV2d;
+  aSurf->D0(p2d.X(), p2d.Y(), aPV2d);
+  //point of vertex in 3D splace
+  gp_Pnt aP3dV = BRep_Tool::Pnt(V);
+
+  Standard_Real aDist3d2 = Max( aPV2d.SquareDistance(aPBound), aP3dV.SquareDistance(aPBound));
+  Standard_Real aTolV = BRep_Tool::Tolerance(V);
+  Standard_Real ttol = aTolV + BRep_Tool::Tolerance(theEdge);
+  if (aDist3d2 <= ttol* ttol) {
     valret = Standard_True;
+
     BRep_Builder B;
-    B.UpdateVertex(V, Max(dmin, BRep_Tool::Tolerance(V)));
+    if( aTolV * aTolV < aDist3d2)
+    {
+      Standard_Real aNewTol = sqrt(aDist3d2) + Precision::Confusion();
+      B.UpdateVertex(V, aNewTol);
+    }
   }
 #ifdef OCCT_DEBUG_MESH
   else {
@@ -609,9 +636,6 @@ void PutPCurve(const TopoDS_Edge& Edg,
 
   Standard_Real f,l;
 
-  //if (!BRep_Tool::CurveOnSurface(Edg,Fac,f,l).IsNull()) {
-  //  return;
-  //}
   Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(Edg,Fac,f,l);
   if ( !aC2d.IsNull() ) {
     gp_Pnt2d p2d;
@@ -712,20 +736,6 @@ void PutPCurve(const TopoDS_Edge& Edg,
       }
     }
 
-/*
-    if (theUmin > Umax-tolu) {
-      while (theUmin > Umax-tolu) {
-       theUmin -= up;
-       nbtra--;
-      }
-    }
-    else if (theUmax < Umin+tolu) {
-      while (theUmax < Umin+tolu) {
-       theUmax += up;
-       nbtra++;
-      }
-    }
-*/
     if (nbtra !=0) {
       C2d->Translate(gp_Vec2d(nbtra*up,0.));
     }
@@ -1010,12 +1020,12 @@ void PutPCurves(const TopoDS_Edge& Efrom,
 
     C->D1(f,pt,d1f);
 
-    ////
+
     TopoDS_Vertex FirstVertex = TopExp::FirstVertex(Efrom);
     Standard_Real vtx_param = BRep_Tool::Parameter(FirstVertex, Efrom);
     BRepAdaptor_Curve2d BAcurve2d(Efrom, Fac);
     gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
-    ////
+
     Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),p2d,Eto,Fac);
     
     C = BRep_Tool::Curve(Eto,Loc,f,l);
@@ -1139,9 +1149,7 @@ void PutPCurves(const TopoDS_Edge& Efrom,
 
 void FindInternalIntersections(const TopoDS_Edge& theEdge,
                                const TopoDS_Face& theFace,
-                               TopTools_IndexedDataMapOfShapeListOfShape& Splits,
-                               TopTools_DataMapOfShapeShape& GlobalMap,
-                               TopTools_MapOfShape& theMap)
+                               TopTools_IndexedDataMapOfShapeListOfShape& Splits)
 {
   Standard_Real TolExt = Precision::PConfusion();
   Standard_Integer i, j, aNbExt;
@@ -1153,16 +1161,19 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
   gp_Pnt thePnt [2];
   thePnt[0] = BRep_Tool::Pnt(theVertices[0]);
   thePnt[1] = BRep_Tool::Pnt(theVertices[1]);
-  
+  Standard_Real aTolV[2];
+  aTolV[0] =BRep_Tool::Tolerance(theVertices[0]);
+  aTolV[1] =BRep_Tool::Tolerance(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;
+  Standard_Real  aFpar, aLpar;
   const Handle(Geom_Curve)& theCurve = BRep_Tool::Curve(theEdge, thePar[0], thePar[1]);
   GeomAdaptor_Curve theGAcurve(theCurve, thePar[0], thePar[1]);
-  
+  Standard_Real aDistMax = Precision::Confusion() * Precision::Confusion();
   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
   for (; Explo.More(); Explo.Next())
   {
@@ -1184,53 +1195,33 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
 
     aNbExt = anExtrema.NbExt();
     Standard_Real MaxTol = Max(BRep_Tool::Tolerance(theEdge), BRep_Tool::Tolerance(anEdge));
+    Standard_Real aMaxTol2 =  MaxTol *  MaxTol;
     for (i = 1; i <= aNbExt; i++)
     {
-      Standard_Real aDist = Sqrt(anExtrema.SquareDistance(i));
-      if (aDist > MaxTol)
+      Standard_Real aDist = anExtrema.SquareDistance(i);
+      if (aDist > aMaxTol2)
         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 (Abs(theIntPar - thePar[j]) <= Precision::PConfusion())
+          break;
       }
-      if (!IntersFound && aDist <= Precision::Confusion()) //intersection is inside "theEdge" => split
+      //intersection found in the middle of the edge
+      if (j >= 2) //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]))
+        if (aPoint.SquareDistance(thePnt[0]) > aTolV[0] * aTolV[0] &&
+            aPoint.SquareDistance(thePnt[1]) > aTolV[1] * aTolV[1])
+        {
           SplitPars.Append(theIntPar);
+          if( aDist > aDistMax)
+            aDistMax = aDist;
+        }
       }
     }
   }
@@ -1247,14 +1238,13 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
         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())
+    if (Pnt1.SquareDistance(Pnt2) <= Precision::Confusion()* Precision::Confusion())
       SplitPars.Remove(i+1);
     else
       i++;
@@ -1263,8 +1253,7 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
   //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++)
@@ -1275,6 +1264,8 @@ void FindInternalIntersections(const TopoDS_Edge& theEdge,
       LastPar = SplitPars(i);
       gp_Pnt LastPoint = theCurve->Value(LastPar);
       LastVertex = BRepLib_MakeVertex(LastPoint);
+      BRep_Builder aB;
+      aB.UpdateVertex(LastVertex, sqrt(aDistMax));
     }
     else
     {
diff --git a/tests/bugs/modalg_6/bug27151 b/tests/bugs/modalg_6/bug27151
new file mode 100644 (file)
index 0000000..6198c4f
--- /dev/null
@@ -0,0 +1,21 @@
+puts "========"
+puts "OCC27151"
+puts "========"
+puts ""
+#########################################################################################
+# Exception is raised during performing command "splitshape" in the Test Harness
+#########################################################################################
+
+restore [locate_data_file bug27151.brep] a
+explode a 
+renamevar a_1 f1
+renamevar a_2 w0
+explode f1 e
+explode w0 e
+wire w1 w0_2 w0_3
+splitshape rs f1 f1 w1 @ f1_4 w0_1
+fixshape res rs 1.e-07 1
+checkprops res -s 173.371
+checknbshapes res -face 2
+
+checkview -display res -3d -path ${imagedir}/${test_image}.png