From 56091b56acdde3591b3fb457ccbc761420c4d267 Mon Sep 17 00:00:00 2001 From: isn Date: Thu, 14 Jul 2016 17:39:03 +0300 Subject: [PATCH] 0027199: Unifysamedomain regression issue in OCCT 7 Allow to process the compounds in UnifySameDomain algorithm. Earlier only faces from shells were allowed to be unified. Test case for issue #27199 --- .../ShapeUpgrade_UnifySameDomain.cxx | 849 ++++++++++-------- .../ShapeUpgrade_UnifySameDomain.hxx | 4 + tests/bugs/modalg_6/bug27199 | 19 + 3 files changed, 475 insertions(+), 397 deletions(-) create mode 100644 tests/bugs/modalg_6/bug27199 diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx index 66312ef339..776b55d3a9 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx @@ -134,6 +134,41 @@ static Standard_Boolean IsLikeSeam(const TopoDS_Edge& anEdge, return Standard_False; } +static Standard_Boolean CheckSharedEdgeOri(const TopoDS_Face& theF1, + const TopoDS_Face& theF2, + const TopoDS_Edge& theE) +{ + TopAbs_Orientation anEOri = theE.Orientation(); + if (anEOri == TopAbs_EXTERNAL || anEOri == TopAbs_INTERNAL) + return Standard_False; + + TopExp_Explorer Exp(theF1, TopAbs_EDGE); + for (;Exp.More();Exp.Next()) + { + const TopoDS_Shape& aCE = Exp.Current(); + if (aCE.IsSame(theE)) + { + anEOri = aCE.Orientation(); + break; + } + } + + for (Exp.Init(theF2, TopAbs_EDGE);Exp.More();Exp.Next()) + { + const TopoDS_Shape& aCE = Exp.Current(); + if (aCE.IsSame(theE)) + { + if (aCE.Orientation() == TopAbs::Reverse(anEOri)) + return Standard_True; + else + return Standard_False; + } + } + + return Standard_False; + +} + //======================================================================= //function : AddOrdinaryEdges //purpose : auxilary @@ -1170,465 +1205,485 @@ void ShapeUpgrade_UnifySameDomain::UnifyFaces() // creating map of edge faces for the whole shape TopTools_IndexedDataMapOfShapeListOfShape aGMapEdgeFaces; TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces); - - // processing each shell + + // unify faces in each shell separately TopExp_Explorer exps; - for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) { - TopoDS_Shell aShell = TopoDS::Shell(exps.Current()); - - // creating map of edge faces for the shell - TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces; - TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces); - - // map of processed shapes - TopTools_MapOfShape aProcessed; - - Standard_Integer NbModif = 0; - Standard_Boolean hasFailed = Standard_False; - Standard_Real tol = Precision::Confusion(); - - // count faces - Standard_Integer nbf = 0; - TopExp_Explorer exp; - TopTools_MapOfShape mapF; - for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) { - if (mapF.Add(exp.Current())) - nbf++; - } + for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) + IntUnifyFaces(exps.Current(), aGMapEdgeFaces, Standard_False); + + // gather all faces out of shells in one compound and unify them at once + BRep_Builder aBB; + TopoDS_Compound aCmp; + aBB.MakeCompound(aCmp); + Standard_Integer nbf = 0; + for (exps.Init(myShape, TopAbs_FACE, TopAbs_SHELL); exps.More(); exps.Next(), nbf++) + aBB.Add(aCmp, exps.Current()); + + if (nbf > 0) + IntUnifyFaces(aCmp, aGMapEdgeFaces, Standard_True); + + myShape = myContext->Apply(myShape); +} - // processing each face - mapF.Clear(); - for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) { - TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD)); - if (aProcessed.Contains(aFace)) - continue; +void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape, + const TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces, + Standard_Boolean IsCheckSharedEdgeOri) +{ + // creating map of edge faces for the shape + TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces; + TopExp::MapShapesAndAncestors(theInpShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces); - Standard_Integer dummy; - TopTools_SequenceOfShape edges; - AddOrdinaryEdges(edges,aFace,dummy); + // map of processed shapes + TopTools_MapOfShape aProcessed; - TopTools_SequenceOfShape faces; - faces.Append(aFace); + Standard_Integer NbModif = 0; + Standard_Boolean hasFailed = Standard_False; + Standard_Real tol = Precision::Confusion(); - //surface and location to construct result - TopLoc_Location aBaseLocation; - Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation); - aBaseSurface = ClearRts(aBaseSurface); + // count faces + Standard_Integer nbf = 0; + TopExp_Explorer exp; + TopTools_MapOfShape mapF; + for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) { + if (mapF.Add(exp.Current())) + nbf++; + } - // find adjacent faces to union - Standard_Integer i; - for (i = 1; i <= edges.Length(); i++) { - TopoDS_Edge edge = TopoDS::Edge(edges(i)); - if (BRep_Tool::Degenerated(edge)) - continue; + // processing each face + mapF.Clear(); + for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) { + TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD)); + + if (aProcessed.Contains(aFace)) + continue; + + Standard_Integer dummy; + TopTools_SequenceOfShape edges; + AddOrdinaryEdges(edges,aFace,dummy); + + TopTools_SequenceOfShape faces; + faces.Append(aFace); - // get connectivity of the edge in the global shape - const TopTools_ListOfShape& aGList = aGMapEdgeFaces.FindFromKey(edge); - if (!myAllowInternal && aGList.Extent() != 2) { - // non mainfold case is not processed unless myAllowInternal + //surface and location to construct result + TopLoc_Location aBaseLocation; + Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation); + aBaseSurface = ClearRts(aBaseSurface); + + // find adjacent faces to union + Standard_Integer i; + for (i = 1; i <= edges.Length(); i++) { + TopoDS_Edge edge = TopoDS::Edge(edges(i)); + if (BRep_Tool::Degenerated(edge)) + continue; + + // get connectivity of the edge in the global shape + const TopTools_ListOfShape& aGList = theGMapEdgeFaces.FindFromKey(edge); + if (!myAllowInternal && aGList.Extent() != 2) { + // non mainfold case is not processed unless myAllowInternal + continue; + } + // process faces connected through the edge in the current shape + const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge); + TopTools_ListIteratorOfListOfShape anIter(aList); + for (; anIter.More(); anIter.Next()) { + TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD)); + if (anCheckedFace.IsSame(aFace)) continue; - } - // process faces connected through the edge in the current shell - const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge); - TopTools_ListIteratorOfListOfShape anIter(aList); - for (; anIter.More(); anIter.Next()) { - TopoDS_Face anCheckedFace = TopoDS::Face(anIter.Value().Oriented(TopAbs_FORWARD)); - if (anCheckedFace.IsSame(aFace)) - continue; - if (aProcessed.Contains(anCheckedFace)) - continue; + if (aProcessed.Contains(anCheckedFace)) + continue; - if (IsSameDomain(aFace,anCheckedFace)) { + if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) ) + continue; - // hotfix for 27271: prevent merging along periodic direction. - if (IsLikeSeam(edge, aFace, aBaseSurface)) - continue; + if (IsSameDomain(aFace,anCheckedFace)) { - // replacing pcurves - TopoDS_Face aMockUpFace; - BRep_Builder B; - B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.); - MovePCurves(aMockUpFace,anCheckedFace); + // hotfix for 27271: prevent merging along periodic direction. + if (IsLikeSeam(edge, aFace, aBaseSurface)) + continue; - if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) { - // sequence edges is modified - i = dummy; - } + // replacing pcurves + TopoDS_Face aMockUpFace; + BRep_Builder B; + B.MakeFace(aMockUpFace,aBaseSurface,aBaseLocation,0.); + MovePCurves(aMockUpFace,anCheckedFace); - faces.Append(anCheckedFace); - aProcessed.Add(anCheckedFace); - break; + if (AddOrdinaryEdges(edges,aMockUpFace,dummy)) { + // sequence edges is modified + i = dummy; } + + faces.Append(anCheckedFace); + aProcessed.Add(anCheckedFace); + break; } } + } - if (faces.Length() > 1) { - // fill in the connectivity map for selected faces - TopTools_IndexedDataMapOfShapeListOfShape aMapEF; - for (i = 1; i <= faces.Length(); i++) { - TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF); - } + if (faces.Length() > 1) { + // fill in the connectivity map for selected faces + TopTools_IndexedDataMapOfShapeListOfShape aMapEF; + for (i = 1; i <= faces.Length(); i++) { + TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF); + } - // Collect multiconnected edges, i.e. edges that are internal to - // the set of selected faces and have connections to other faces. - TopTools_ListOfShape aMultEdges; - for (i = 1; i <= aMapEF.Extent(); i++) { - const TopTools_ListOfShape& aLF = aMapEF(i); - if (aLF.Extent() == 2) { - const TopoDS_Shape& aE = aMapEF.FindKey(i); - const TopTools_ListOfShape& aGLF = aGMapEdgeFaces.FindFromKey(aE); - if (aGLF.Extent() > 2) { - aMultEdges.Append(aE); - } + // Collect multiconnected edges, i.e. edges that are internal to + // the set of selected faces and have connections to other faces. + TopTools_ListOfShape aMultEdges; + for (i = 1; i <= aMapEF.Extent(); i++) { + const TopTools_ListOfShape& aLF = aMapEF(i); + if (aLF.Extent() == 2) { + const TopoDS_Shape& aE = aMapEF.FindKey(i); + const TopTools_ListOfShape& aGLF = theGMapEdgeFaces.FindFromKey(aE); + if (aGLF.Extent() > 2) { + aMultEdges.Append(aE); } } - if (!aMultEdges.IsEmpty()) { - if (!myAllowInternal) { - // Remove from the selection the faces containing multiconnected edges - TopTools_MapOfShape anAvoidFaces; - TopTools_ListIteratorOfListOfShape it(aMultEdges); - for (; it.More(); it.Next()) { - const TopoDS_Shape& aE = it.Value(); - const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); - anAvoidFaces.Add(aLF.First()); - anAvoidFaces.Add(aLF.Last()); - } - for (i = 1; i <= faces.Length(); ) { - if (anAvoidFaces.Contains(faces(i))) { - // update the boundaries of merged area, for that - // remove from 'edges' the edges of this face and add to 'edges' - // the edges of this face that were not present in 'edges' before - TopExp_Explorer ex(faces(i), TopAbs_EDGE); - for (; ex.More(); ex.Next()) { - TopoDS_Shape aE = ex.Current(); - Standard_Integer j; - for (j = 1; j <= edges.Length(); j++) { - if (edges(j).IsSame(aE)) - break; - } - if (j <= edges.Length()) - edges.Remove(j); - else - edges.Append(aE); + } + if (!aMultEdges.IsEmpty()) { + if (!myAllowInternal) { + // Remove from the selection the faces containing multiconnected edges + TopTools_MapOfShape anAvoidFaces; + TopTools_ListIteratorOfListOfShape it(aMultEdges); + for (; it.More(); it.Next()) { + const TopoDS_Shape& aE = it.Value(); + const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); + anAvoidFaces.Add(aLF.First()); + anAvoidFaces.Add(aLF.Last()); + } + for (i = 1; i <= faces.Length(); ) { + if (anAvoidFaces.Contains(faces(i))) { + // update the boundaries of merged area, for that + // remove from 'edges' the edges of this face and add to 'edges' + // the edges of this face that were not present in 'edges' before + TopExp_Explorer ex(faces(i), TopAbs_EDGE); + for (; ex.More(); ex.Next()) { + TopoDS_Shape aE = ex.Current(); + Standard_Integer j; + for (j = 1; j <= edges.Length(); j++) { + if (edges(j).IsSame(aE)) + break; } - faces.Remove(i); + if (j <= edges.Length()) + edges.Remove(j); + else + edges.Append(aE); } - else - i++; + faces.Remove(i); } + else + i++; } - else { - // add multiconnected edges as internal in new face - TopTools_ListIteratorOfListOfShape it(aMultEdges); - for (; it.More(); it.Next()) { - const TopoDS_Shape& aE = it.Value(); - edges.Append(aE.Oriented(TopAbs_INTERNAL)); - } + } + else { + // add multiconnected edges as internal in new face + TopTools_ListIteratorOfListOfShape it(aMultEdges); + for (; it.More(); it.Next()) { + const TopoDS_Shape& aE = it.Value(); + edges.Append(aE.Oriented(TopAbs_INTERNAL)); } } } + } - // all faces collected in the sequence. Perform union of faces - if (faces.Length() > 1) { - NbModif++; - TopoDS_Face aResult; - BRep_Builder B; - B.MakeFace(aResult,aBaseSurface,aBaseLocation,0); - Standard_Integer nbWires = 0; - - TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD))); - // connecting wires - while (edges.Length()>0) { - - Standard_Boolean isEdge3d = Standard_False; - nbWires++; - TopTools_MapOfShape aVertices; - TopoDS_Wire aWire; - B.MakeWire(aWire); - - TopoDS_Edge anEdge = TopoDS::Edge(edges(1)); - edges.Remove(1); - // collect internal edges in separate wires - Standard_Boolean isInternal = (anEdge.Orientation() == TopAbs_INTERNAL); - - isEdge3d |= !BRep_Tool::Degenerated(anEdge); - B.Add(aWire,anEdge); - TopoDS_Vertex V1,V2; - TopExp::Vertices(anEdge,V1,V2); - aVertices.Add(V1); - aVertices.Add(V2); - - Standard_Boolean isNewFound = Standard_False; - do { - isNewFound = Standard_False; - for(Standard_Integer j = 1; j <= edges.Length(); j++) { - anEdge = TopoDS::Edge(edges(j)); - // check if the current edge orientation corresponds to the first one - Standard_Boolean isCurrInternal = (anEdge.Orientation() == TopAbs_INTERNAL); - if (isCurrInternal != isInternal) - continue; - TopExp::Vertices(anEdge,V1,V2); - if(aVertices.Contains(V1) || aVertices.Contains(V2)) { - isEdge3d |= !BRep_Tool::Degenerated(anEdge); - aVertices.Add(V1); - aVertices.Add(V2); - B.Add(aWire,anEdge); - edges.Remove(j); - j--; - isNewFound = Standard_True; - } - } - } while (isNewFound); - - // sorting any type of edges - aWire.Closed (BRep_Tool::IsClosed (aWire)); - aWire = TopoDS::Wire(myContext->Apply(aWire)); - - Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion()); - sfw->FixReorder(); - Standard_Boolean isDegRemoved = Standard_False; - if(!sfw->StatusReorder ( ShapeExtend_FAIL )) { - // clear degenerated edges if at least one with 3d curve exist - if(isEdge3d) { - Handle(ShapeExtend_WireData) sewd = sfw->WireData(); - for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) { - TopoDS_Edge E = sewd->Edge(j); - if(BRep_Tool::Degenerated(E)) { - sewd->Remove(j); - isDegRemoved = Standard_True; - j--; - } - } + // all faces collected in the sequence. Perform union of faces + if (faces.Length() > 1) { + NbModif++; + TopoDS_Face aResult; + BRep_Builder B; + B.MakeFace(aResult,aBaseSurface,aBaseLocation,0); + Standard_Integer nbWires = 0; + + TopoDS_Face tmpF = TopoDS::Face(myContext->Apply(faces(1).Oriented(TopAbs_FORWARD))); + // connecting wires + while (edges.Length()>0) { + + Standard_Boolean isEdge3d = Standard_False; + nbWires++; + TopTools_MapOfShape aVertices; + TopoDS_Wire aWire; + B.MakeWire(aWire); + + TopoDS_Edge anEdge = TopoDS::Edge(edges(1)); + edges.Remove(1); + // collect internal edges in separate wires + Standard_Boolean isInternal = (anEdge.Orientation() == TopAbs_INTERNAL); + + isEdge3d |= !BRep_Tool::Degenerated(anEdge); + B.Add(aWire,anEdge); + TopoDS_Vertex V1,V2; + TopExp::Vertices(anEdge,V1,V2); + aVertices.Add(V1); + aVertices.Add(V2); + + Standard_Boolean isNewFound = Standard_False; + do { + isNewFound = Standard_False; + for(Standard_Integer j = 1; j <= edges.Length(); j++) { + anEdge = TopoDS::Edge(edges(j)); + // check if the current edge orientation corresponds to the first one + Standard_Boolean isCurrInternal = (anEdge.Orientation() == TopAbs_INTERNAL); + if (isCurrInternal != isInternal) + continue; + TopExp::Vertices(anEdge,V1,V2); + if(aVertices.Contains(V1) || aVertices.Contains(V2)) { + isEdge3d |= !BRep_Tool::Degenerated(anEdge); + aVertices.Add(V1); + aVertices.Add(V2); + B.Add(aWire,anEdge); + edges.Remove(j); + j--; + isNewFound = Standard_True; } - sfw->FixShifted(); - if(isDegRemoved) - sfw->FixDegenerated(); - } - TopoDS_Wire aWireFixed = sfw->Wire(); - //aContext->Replace(aWire,aWireFixed); - myContext->Replace(aWire,aWireFixed); - //for history - /* - if (!myOldNewMap.IsBound(aWire)) - { - TopTools_ListOfShape EmptyList; - myOldNewMap.Bind(aWire, EmptyList); } - myOldNewMap(aWire).Clear(); - myOldNewMap(aWire).Append(aWireFixed); - */ - ///////////// - - // add resulting wire + } while (isNewFound); + + // sorting any type of edges + aWire.Closed (BRep_Tool::IsClosed (aWire)); + aWire = TopoDS::Wire(myContext->Apply(aWire)); + + Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire(aWire,tmpF,Precision::Confusion()); + sfw->FixReorder(); + Standard_Boolean isDegRemoved = Standard_False; + if(!sfw->StatusReorder ( ShapeExtend_FAIL )) { + // clear degenerated edges if at least one with 3d curve exist if(isEdge3d) { - B.Add(aResult,aWireFixed); - } - else { - // sorting edges - Handle(ShapeExtend_WireData) sbwd = sfw->WireData(); - Standard_Integer nbEdges = sbwd->NbEdges(); - // sort degenerated edges and create one edge instead of several ones - ShapeAnalysis_WireOrder sawo(Standard_False, 0); - ShapeAnalysis_Edge sae; - Standard_Integer aLastEdge = nbEdges; - for(Standard_Integer j = 1; j <= nbEdges; j++) { - Standard_Real f,l; - //smh protection on NULL pcurve - Handle(Geom2d_Curve) c2d; - if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) { - aLastEdge--; - continue; + Handle(ShapeExtend_WireData) sewd = sfw->WireData(); + for(Standard_Integer j = 1; j<=sewd->NbEdges();j++) { + TopoDS_Edge E = sewd->Edge(j); + if(BRep_Tool::Degenerated(E)) { + sewd->Remove(j); + isDegRemoved = Standard_True; + j--; } - sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY()); } - sawo.Perform(); - - // constructind one degenerative edge - gp_XY aStart, anEnd, tmp; - Standard_Integer nbFirst = sawo.Ordered(1); - TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD)); - ShapeBuild_Edge sbe; - TopoDS_Vertex aDummyV; - TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV); - sawo.XY(nbFirst,aStart,tmp); - sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd); - - gp_XY aVec = anEnd-aStart; - Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart)); - - B.UpdateEdge(E,aLine,tmpF,0.); - B.Range(E,tmpF,0.,aVec.Modulus()); - Handle(Geom_Curve) C3d; - B.UpdateEdge(E,C3d,0.); - B.Degenerated(E,Standard_True); - TopoDS_Wire aW; - B.MakeWire(aW); - B.Add(aW,E); - aW.Closed (Standard_True); - B.Add(aResult,aW); } + sfw->FixShifted(); + if(isDegRemoved) + sfw->FixDegenerated(); } - - // perform substitution of face - //aContext->Replace(aContext->Apply(aFace),aResult); - myContext->Replace(myContext->Apply(aFace),aResult); + TopoDS_Wire aWireFixed = sfw->Wire(); + //aContext->Replace(aWire,aWireFixed); + myContext->Replace(aWire,aWireFixed); //for history /* - if (!myOldNewMap.IsBound(aFace)) + if (!myOldNewMap.IsBound(aWire)) { - TopTools_ListOfShape EmptyList; - myOldNewMap.Bind(aFace, EmptyList); + TopTools_ListOfShape EmptyList; + myOldNewMap.Bind(aWire, EmptyList); } - myOldNewMap(aFace).Clear(); - myOldNewMap(aFace).Append(aResult); + myOldNewMap(aWire).Clear(); + myOldNewMap(aWire).Append(aWireFixed); */ ///////////// - ShapeFix_Face sff (aResult); - //Intializing by tolerances - sff.SetPrecision(Precision::Confusion()); - sff.SetMinTolerance(tol); - sff.SetMaxTolerance(1.); - //Setting modes - sff.FixOrientationMode() = 0; - //sff.FixWireMode() = 0; - //sff.SetContext(aContext); - sff.SetContext(myContext); - // Applying the fixes - sff.Perform(); - if(sff.Status(ShapeExtend_FAIL)) - hasFailed = Standard_True; - - // breaking down to several faces - //TopoDS_Shape theResult = aContext->Apply(aResult); - TopoDS_Shape theResult = myContext->Apply(aResult); - for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) { - TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD)); - Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 ); - grid->SetValue ( 1, 1, aBaseSurface ); - Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid ); - ShapeFix_ComposeShell CompShell; - CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision - //CompShell.SetContext( aContext ); - CompShell.SetContext( myContext ); - - TopTools_SequenceOfShape parts, anIntWires; - ShapeFix_SequenceOfWireSegment wires; - for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) { - const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current()); - // check if the wire is ordinary (contains non-internal edges) - Standard_Boolean isInternal = Standard_True; - for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next()) - isInternal = (it.Value().Orientation() == TopAbs_INTERNAL); - if (isInternal) - { - // place internal wire separately - anIntWires.Append(aWire); - } - else - { - Handle(ShapeExtend_WireData) sbwd = - new ShapeExtend_WireData (aWire); - ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED ); - wires.Append(seg); + // add resulting wire + if(isEdge3d) { + B.Add(aResult,aWireFixed); + } + else { + // sorting edges + Handle(ShapeExtend_WireData) sbwd = sfw->WireData(); + Standard_Integer nbEdges = sbwd->NbEdges(); + // sort degenerated edges and create one edge instead of several ones + ShapeAnalysis_WireOrder sawo(Standard_False, 0); + ShapeAnalysis_Edge sae; + Standard_Integer aLastEdge = nbEdges; + for(Standard_Integer j = 1; j <= nbEdges; j++) { + Standard_Real f,l; + //smh protection on NULL pcurve + Handle(Geom2d_Curve) c2d; + if(!sae.PCurve(sbwd->Edge(j),tmpF,c2d,f,l)) { + aLastEdge--; + continue; } + sawo.Add(c2d->Value(f).XY(),c2d->Value(l).XY()); } + sawo.Perform(); + + // constructind one degenerative edge + gp_XY aStart, anEnd, tmp; + Standard_Integer nbFirst = sawo.Ordered(1); + TopoDS_Edge anOrigE = TopoDS::Edge(sbwd->Edge(nbFirst).Oriented(TopAbs_FORWARD)); + ShapeBuild_Edge sbe; + TopoDS_Vertex aDummyV; + TopoDS_Edge E = sbe.CopyReplaceVertices(anOrigE,aDummyV,aDummyV); + sawo.XY(nbFirst,aStart,tmp); + sawo.XY(sawo.Ordered(aLastEdge),tmp,anEnd); + + gp_XY aVec = anEnd-aStart; + Handle(Geom2d_Line) aLine = new Geom2d_Line(aStart,gp_Dir2d(anEnd-aStart)); + + B.UpdateEdge(E,aLine,tmpF,0.); + B.Range(E,tmpF,0.,aVec.Modulus()); + Handle(Geom_Curve) C3d; + B.UpdateEdge(E,C3d,0.); + B.Degenerated(E,Standard_True); + TopoDS_Wire aW; + B.MakeWire(aW); + B.Add(aW,E); + aW.Closed (Standard_True); + B.Add(aResult,aW); + } + } - CompShell.DispatchWires ( parts,wires ); - for (Standard_Integer j=1; j <= parts.Length(); j++ ) { - ShapeFix_Face aFixOrient(TopoDS::Face(parts(j))); - //aFixOrient.SetContext(aContext); - aFixOrient.SetContext(myContext); - aFixOrient.FixOrientation(); - // put internal wires to faces - putIntWires(parts(j), anIntWires); - } + // perform substitution of face + //aContext->Replace(aContext->Apply(aFace),aResult); + myContext->Replace(myContext->Apply(aFace),aResult); + //for history + /* + if (!myOldNewMap.IsBound(aFace)) + { + TopTools_ListOfShape EmptyList; + myOldNewMap.Bind(aFace, EmptyList); + } + myOldNewMap(aFace).Clear(); + myOldNewMap(aFace).Append(aResult); + */ + ///////////// - TopoDS_Shape CompRes; - if ( parts.Length() !=1 ) { - TopoDS_Shell S; - B.MakeShell ( S ); - for ( i=1; i <= parts.Length(); i++ ) - B.Add ( S, parts(i) ); - S.Closed (BRep_Tool::IsClosed (S)); - CompRes = S; - } - else CompRes = parts(1); + ShapeFix_Face sff (aResult); + //Intializing by tolerances + sff.SetPrecision(Precision::Confusion()); + sff.SetMinTolerance(tol); + sff.SetMaxTolerance(1.); + //Setting modes + sff.FixOrientationMode() = 0; + //sff.FixWireMode() = 0; + //sff.SetContext(aContext); + sff.SetContext(myContext); + // Applying the fixes + sff.Perform(); + if(sff.Status(ShapeExtend_FAIL)) + hasFailed = Standard_True; - //aContext->Replace(aCurrent,CompRes); - myContext->Replace(aCurrent,CompRes); - //for history - /* - if (!myOldNewMap.IsBound(aCurrent)) + // breaking down to several faces + //TopoDS_Shape theResult = aContext->Apply(aResult); + TopoDS_Shape theResult = myContext->Apply(aResult); + for (TopExp_Explorer aFaceExp (theResult,TopAbs_FACE); aFaceExp.More(); aFaceExp.Next()) { + TopoDS_Face aCurrent = TopoDS::Face(aFaceExp.Current().Oriented(TopAbs_FORWARD)); + Handle(TColGeom_HArray2OfSurface) grid = new TColGeom_HArray2OfSurface ( 1, 1, 1, 1 ); + grid->SetValue ( 1, 1, aBaseSurface ); + Handle(ShapeExtend_CompositeSurface) G = new ShapeExtend_CompositeSurface ( grid ); + ShapeFix_ComposeShell CompShell; + CompShell.Init ( G, aBaseLocation, aCurrent, ::Precision::Confusion() );//myPrecision + //CompShell.SetContext( aContext ); + CompShell.SetContext( myContext ); + + TopTools_SequenceOfShape parts, anIntWires; + ShapeFix_SequenceOfWireSegment wires; + for(TopExp_Explorer W_Exp(aCurrent,TopAbs_WIRE);W_Exp.More();W_Exp.Next()) { + const TopoDS_Wire& aWire = TopoDS::Wire(W_Exp.Current()); + // check if the wire is ordinary (contains non-internal edges) + Standard_Boolean isInternal = Standard_True; + for (TopoDS_Iterator it(aWire); it.More() && isInternal; it.Next()) + isInternal = (it.Value().Orientation() == TopAbs_INTERNAL); + if (isInternal) { - TopTools_ListOfShape EmptyList; - myOldNewMap.Bind(aCurrent, EmptyList); + // place internal wire separately + anIntWires.Append(aWire); + } + else + { + Handle(ShapeExtend_WireData) sbwd = + new ShapeExtend_WireData (aWire); + ShapeFix_WireSegment seg ( sbwd, TopAbs_REVERSED ); + wires.Append(seg); } - myOldNewMap(aCurrent).Clear(); - myOldNewMap(aCurrent).Append(CompRes); - */ - ///////////// } - // remove the remaining faces - for(i = 2; i <= faces.Length(); i++) - { - myOldShapes.Bind(faces(i), theResult); - myContext->Remove(faces(i)); + CompShell.DispatchWires ( parts,wires ); + for (Standard_Integer j=1; j <= parts.Length(); j++ ) { + ShapeFix_Face aFixOrient(TopoDS::Face(parts(j))); + //aFixOrient.SetContext(aContext); + aFixOrient.SetContext(myContext); + aFixOrient.FixOrientation(); + // put internal wires to faces + putIntWires(parts(j), anIntWires); } - } - } // end processing each face - - //TopoDS_Shape aResult = Shape; - if (NbModif > 0 && !hasFailed) { - //TopoDS_Shape aResult = aContext->Apply(aShell); - TopoDS_Shape aResult = myContext->Apply(aShell); - - ShapeFix_Edge sfe; - if (!myContext.IsNull()) sfe.SetContext(myContext); - for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) { - TopoDS_Edge E = TopoDS::Edge(exp.Current()); - sfe.FixVertexTolerance (E); - // ptv add fix same parameter - sfe.FixSameParameter(E, Precision::Confusion()); - } - myContext->Replace(aShell, aResult); - //for history - /* - if (!myOldNewMap.IsBound(aShell)) - { + TopoDS_Shape CompRes; + if ( parts.Length() !=1 ) { + TopoDS_Shell S; + B.MakeShell ( S ); + for ( i=1; i <= parts.Length(); i++ ) + B.Add ( S, parts(i) ); + S.Closed (BRep_Tool::IsClosed (S)); + CompRes = S; + } + else CompRes = parts(1); + + //aContext->Replace(aCurrent,CompRes); + myContext->Replace(aCurrent,CompRes); + //for history + /* + if (!myOldNewMap.IsBound(aCurrent)) + { TopTools_ListOfShape EmptyList; - myOldNewMap.Bind(aShell, EmptyList); + myOldNewMap.Bind(aCurrent, EmptyList); + } + myOldNewMap(aCurrent).Clear(); + myOldNewMap(aCurrent).Append(CompRes); + */ + ///////////// } - myOldNewMap(aShell).Clear(); - myOldNewMap(aShell).Append(aResult); - */ - ///////////// + + // remove the remaining faces + for(i = 2; i <= faces.Length(); i++) + { + myOldShapes.Bind(faces(i), theResult); + myContext->Remove(faces(i)); + } + } + } // end processing each face + + //TopoDS_Shape aResult = Shape; + if (NbModif > 0 && !hasFailed) { + //TopoDS_Shape aResult = aContext->Apply(aShell); + TopoDS_Shape aResult = myContext->Apply(theInpShape); + + ShapeFix_Edge sfe; + if (!myContext.IsNull()) sfe.SetContext(myContext); + for (exp.Init(aResult,TopAbs_EDGE); exp.More(); exp.Next()) { + TopoDS_Edge E = TopoDS::Edge(exp.Current()); + sfe.FixVertexTolerance (E); + // ptv add fix same parameter + sfe.FixSameParameter(E, Precision::Confusion()); } - //else + + myContext->Replace(theInpShape, aResult); + //for history + /* + if (!myOldNewMap.IsBound(aShell)) { - for (exp.Init(aShell, TopAbs_FACE); exp.More(); exp.Next()) { - TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD)); - Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire; - sfw->SetContext(myContext); - sfw->SetPrecision(Precision::Confusion()); - sfw->SetMinTolerance(Precision::Confusion()); - sfw->SetMaxTolerance(1.); - sfw->SetFace(aFace); - for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) { - TopoDS_Wire wire = TopoDS::Wire(iter.Value()); - sfw->Load(wire); - sfw->FixReorder(); - sfw->FixShifted(); - } + TopTools_ListOfShape EmptyList; + myOldNewMap.Bind(aShell, EmptyList); + } + myOldNewMap(aShell).Clear(); + myOldNewMap(aShell).Append(aResult); + */ + ///////////// + } + //else + { + for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) { + TopoDS_Face aFace = TopoDS::Face(exp.Current().Oriented(TopAbs_FORWARD)); + Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire; + sfw->SetContext(myContext); + sfw->SetPrecision(Precision::Confusion()); + sfw->SetMinTolerance(Precision::Confusion()); + sfw->SetMaxTolerance(1.); + sfw->SetFace(aFace); + for (TopoDS_Iterator iter (aFace,Standard_False); iter.More(); iter.Next()) { + TopoDS_Wire wire = TopoDS::Wire(iter.Value()); + sfw->Load(wire); + sfw->FixReorder(); + sfw->FixShifted(); } } - } // end processing each shell + } - myShape = myContext->Apply(myShape); } //======================================================================= diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx index 452a727883..de185b65ce 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx @@ -24,6 +24,7 @@ #include #include #include +#include class ShapeBuild_ReShape; class TopoDS_Shape; @@ -94,6 +95,9 @@ protected: private: + void IntUnifyFaces(const TopoDS_Shape& theInpShape, + const TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces, + Standard_Boolean IsCheckSharedEdgeOri); TopoDS_Shape myInitShape; Standard_Boolean myUnifyFaces; diff --git a/tests/bugs/modalg_6/bug27199 b/tests/bugs/modalg_6/bug27199 new file mode 100644 index 0000000000..d3defa4d10 --- /dev/null +++ b/tests/bugs/modalg_6/bug27199 @@ -0,0 +1,19 @@ +puts "========" +puts "OCC27199" +puts "========" +puts "" +############################################## +# Unifysamedomain regression issue in OCCT 7 +############################################## + +restore [locate_data_file bug27199_i1_i2.brep] sh + +explode sh +bop sh_1 sh_2 +bopfuse r +unifysamedom result r +checkshape result + +checknbshapes result -face 1 + +checkview -display result -2d -path ${imagedir}/${test_image}.png -- 2.39.5