From: jgv Date: Fri, 6 Apr 2012 07:52:38 +0000 (+0400) Subject: 0022946: BRepFeat_SplitShape crashes on splitting a face by two edges X-Git-Tag: V6_5_3~29 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=ed60a55e7f0a6c77387672f71d6cc855d4be1216 0022946: BRepFeat_SplitShape crashes on splitting a face by two edges null check for pcurve added to avoid exceptions Correction to avoid the regression: check after PutPCurve(edg,fac) --- diff --git a/src/BRepFeat/BRepFeat_SplitShape.cdl b/src/BRepFeat/BRepFeat_SplitShape.cdl index 2850b43117..8f5ddb00dc 100755 --- a/src/BRepFeat/BRepFeat_SplitShape.cdl +++ b/src/BRepFeat/BRepFeat_SplitShape.cdl @@ -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 on the face . The + -- compound must consist of edges lying on the + -- face . If edges are geometrically connected, + -- they must be connected topologically, i.e. they + -- must share common vertices. + -- + -- Raises NoSuchObject if 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; diff --git a/src/BRepFeat/BRepFeat_SplitShape.lxx b/src/BRepFeat/BRepFeat_SplitShape.lxx index 650c80dc63..2019d52def 100755 --- a/src/BRepFeat/BRepFeat_SplitShape.lxx +++ b/src/BRepFeat/BRepFeat_SplitShape.lxx @@ -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 diff --git a/src/BRepTest/BRepTest_FeatureCommands.cxx b/src/BRepTest/BRepTest_FeatureCommands.cxx index 5198d79605..2e57e5342d 100755 --- a/src/BRepTest/BRepTest_FeatureCommands.cxx +++ b/src/BRepTest/BRepTest_FeatureCommands.cxx @@ -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); diff --git a/src/LocOpe/LocOpe_ProjectedWires.cdl b/src/LocOpe/LocOpe_ProjectedWires.cdl index bf30bd0ea6..999dc13505 100755 --- a/src/LocOpe/LocOpe_ProjectedWires.cdl +++ b/src/LocOpe/LocOpe_ProjectedWires.cdl @@ -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; diff --git a/src/LocOpe/LocOpe_SplitShape.cdl b/src/LocOpe/LocOpe_SplitShape.cdl index 1a87b369c3..739b47fbf4 100755 --- a/src/LocOpe/LocOpe_SplitShape.cdl +++ b/src/LocOpe/LocOpe_SplitShape.cdl @@ -92,6 +92,14 @@ is -- wire(s) of a sub-face of is static; + Add(me: in out; Lwires: ListOfShape from TopTools; + F: Face from TopoDS) + ---Purpose: Adds the list of wires on the face . + raises NoSuchObject from Standard, + -- if does not belong to the original shape. + ConstructionError from Standard + is static; + Shape(me) ---Purpose: Returns the "original" shape. diff --git a/src/LocOpe/LocOpe_SplitShape.cxx b/src/LocOpe/LocOpe_SplitShape.cxx index 9fba29138b..907c755c4b 100755 --- a/src/LocOpe/LocOpe_SplitShape.cxx +++ b/src/LocOpe/LocOpe_SplitShape.cxx @@ -27,14 +27,19 @@ #include #include #include +#include +#include +#include #include #include #include #include #include #include +#include #include #include +#include #include #include @@ -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 +//======================================================================= + +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; +} diff --git a/src/LocOpe/LocOpe_Spliter.cxx b/src/LocOpe/LocOpe_Spliter.cxx index cdbacffec4..9f23592c1a 100755 --- a/src/LocOpe/LocOpe_Spliter.cxx +++ b/src/LocOpe/LocOpe_Spliter.cxx @@ -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); } diff --git a/src/LocOpe/LocOpe_WiresOnShape.cdl b/src/LocOpe/LocOpe_WiresOnShape.cdl index 4111f0257c..7dc9ba680f 100755 --- a/src/LocOpe/LocOpe_WiresOnShape.cdl +++ b/src/LocOpe/LocOpe_WiresOnShape.cdl @@ -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 . 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; diff --git a/src/LocOpe/LocOpe_WiresOnShape.cxx b/src/LocOpe/LocOpe_WiresOnShape.cxx index d6a4df89b5..484978360f 100755 --- a/src/LocOpe/LocOpe_WiresOnShape.cxx +++ b/src/LocOpe/LocOpe_WiresOnShape.cxx @@ -53,6 +53,14 @@ #include #include +#include +#include +#include +#include +#include +#include + + 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); +} diff --git a/src/LocOpe/LocOpe_WiresOnShape.lxx b/src/LocOpe/LocOpe_WiresOnShape.lxx index 340455ac1f..f334fae9ce 100755 --- a/src/LocOpe/LocOpe_WiresOnShape.lxx +++ b/src/LocOpe/LocOpe_WiresOnShape.lxx @@ -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)); +}