diff --git a/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx b/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx index 45c39fd7e1..4735f8fc16 100644 --- a/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx +++ b/src/SWDRAW/SWDRAW_ShapeUpgrade.cxx @@ -1284,14 +1284,16 @@ static ShapeUpgrade_UnifySameDomain& Unifier() { //======================================================================= static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, const char** a) { - if (n < 3 || n > 6) + if (n < 3) { - di << "Use unifysamedom result shape [-f] [-e] [+b] [-i]\n"; + di << "Use unifysamedom result shape [-f] [-e] [+b] [-i] [-t val] [-a val]\n"; di << "options:\n"; - di << "[-f] to switch off 'unify-faces' mode \n"; - di << "[-e] to switch off 'unify-edges' mode\n"; - di << "[+b] to switch on 'concat bspline' mode\n"; - di << "[+i] to switch on 'allow internal edges' mode\n"; + di << "-f to switch off 'unify-faces' mode \n"; + di << "-e to switch off 'unify-edges' mode\n"; + di << "+b to switch on 'concat bspline' mode\n"; + di << "+i to switch on 'allow internal edges' mode\n"; + di << "-t val to set linear tolerance\n"; + di << "-a val to set angular tolerance\n"; di << "'unify-faces' and 'unify-edges' modes are switched on by default"; return 1; } @@ -1305,6 +1307,8 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c Standard_Boolean anUEdges = Standard_True; Standard_Boolean anConBS = Standard_False; Standard_Boolean isAllowInternal = Standard_False; + Standard_Real aLinTol = Precision::Confusion(); + Standard_Real aAngTol = Precision::Angular(); if (n > 3) for ( int i = 3; i < n; i++ ) @@ -1317,10 +1321,24 @@ static Standard_Integer unifysamedom(Draw_Interpretor& di, Standard_Integer n, c anConBS = Standard_True; else if (!strcmp(a[i], "+i")) isAllowInternal = Standard_True; + else if (!strcmp(a[i], "-t") || !strcmp(a[i], "-a")) + { + if (++i < n) + { + (a[i-1][1] == 't' ? aLinTol : aAngTol) = Draw::Atof(a[i]); + } + else + { + di << "value expected after " << a[i-1]; + return 1; + } + } } Unifier().Initialize(aShape, anUEdges, anUFaces, anConBS); Unifier().AllowInternalEdges(isAllowInternal); + Unifier().SetLinearTolerance(aLinTol); + Unifier().SetAngularTolerance(aAngTol); Unifier().Build(); TopoDS_Shape Result = Unifier().Shape(); @@ -1556,7 +1574,7 @@ Standard_Integer reshape(Draw_Interpretor& di, theCommands.Add ("removeloc","result shape",__FILE__,removeloc,g); theCommands.Add ("unifysamedom", - "unifysamedom result shape [-f] [-e] [+b]", __FILE__,unifysamedom,g); + "unifysamedom result shape [-f] [-e] [+b] [-i] [-t val] [-a val]", __FILE__,unifysamedom,g); theCommands.Add ("unifysamedomgen", "unifysamedomgen newshape oldshape : get new shape generated " diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx index 776b55d3a9..014d20c393 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx @@ -306,7 +306,9 @@ static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface) //purpose : //======================================================================= static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, - const TopoDS_Face& aCheckedFace) + const TopoDS_Face& aCheckedFace, + const Standard_Real theLinTol, + const Standard_Real theAngTol) { //checking the same handles TopLoc_Location L1, L2; @@ -318,9 +320,6 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, if (S1 == S2 && L1 == L2) return Standard_True; - // planar and cylindrical cases (IMP 20052) - Standard_Real aPrec = Precision::Confusion(); - S1 = BRep_Tool::Surface(aFace); S2 = BRep_Tool::Surface(aCheckedFace); @@ -333,6 +332,22 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface(); //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface(); + // case of two planar surfaces: + // all kinds of surfaces checked, including b-spline and bezier + GeomLib_IsPlanarSurface aPlanarityChecker1(S1, theLinTol); + if (aPlanarityChecker1.IsPlanar()) { + GeomLib_IsPlanarSurface aPlanarityChecker2(S2, theLinTol); + if (aPlanarityChecker2.IsPlanar()) { + gp_Pln aPln1 = aPlanarityChecker1.Plan(); + gp_Pln aPln2 = aPlanarityChecker2.Plan(); + + if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), theAngTol) && + aPln1.Distance(aPln2) < theLinTol) { + return Standard_True; + } + } + } + // case of two elementary surfaces: use OCCT tool // elementary surfaces: ConicalSurface, CylindricalSurface, // Plane, SphericalSurface and ToroidalSurface @@ -346,7 +361,7 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool(); try { - IntPatch_ImpImpIntersection anIIInt (aGA1, aTT1, aGA2, aTT2, aPrec, aPrec); + IntPatch_ImpImpIntersection anIIInt(aGA1, aTT1, aGA2, aTT2, theLinTol, theLinTol); if (!anIIInt.IsDone() || anIIInt.IsEmpty()) return Standard_False; @@ -357,22 +372,6 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, } } - // case of two planar surfaces: - // all kinds of surfaces checked, including b-spline and bezier - GeomLib_IsPlanarSurface aPlanarityChecker1 (S1, aPrec); - if (aPlanarityChecker1.IsPlanar()) { - GeomLib_IsPlanarSurface aPlanarityChecker2 (S2, aPrec); - if (aPlanarityChecker2.IsPlanar()) { - gp_Pln aPln1 = aPlanarityChecker1.Plan(); - gp_Pln aPln2 = aPlanarityChecker2.Plan(); - - if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(),Precision::Angular()) && - aPln1.Distance(aPln2) < aPrec) { - return Standard_True; - } - } - } - // case of two cylindrical surfaces, at least one of which is a swept surface // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) || @@ -382,14 +381,14 @@ static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, { gp_Cylinder aCyl1, aCyl2; if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) { - if (fabs(aCyl1.Radius() - aCyl2.Radius()) < aPrec) { + if (fabs(aCyl1.Radius() - aCyl2.Radius()) < theLinTol) { gp_Dir aDir1 = aCyl1.Position().Direction(); gp_Dir aDir2 = aCyl2.Position().Direction(); if (aDir1.IsParallel(aDir2, Precision::Angular())) { gp_Pnt aLoc1 = aCyl1.Location(); gp_Pnt aLoc2 = aCyl2.Location(); gp_Vec aVec12 (aLoc1, aLoc2); - if (aVec12.SquareMagnitude() < aPrec*aPrec || + if (aVec12.SquareMagnitude() < theLinTol*theLinTol || aVec12.IsParallel(aDir1, Precision::Angular())) { return Standard_True; } @@ -1055,8 +1054,11 @@ static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges, k++; for (Standard_Integer j = 2; j <= SeqOfSubsSeqOfEdges(i).SeqsEdges.Length(); j++) { - TopoDS_Shape OldEdge = NewEdges2OldEdges(SeqOfSubsSeqOfEdges(i).SeqsEdges(j)); - theOldShapes.Bind(OldEdge, SeqOfSubsSeqOfEdges(i).UnionEdges); + const TopoDS_Shape& anOldEdge = SeqOfSubsSeqOfEdges(i).SeqsEdges(j); + const TopoDS_Shape* pOrigEdge = NewEdges2OldEdges.Seek(anOldEdge); + if (!pOrigEdge) + pOrigEdge = &anOldEdge; + theOldShapes.Bind(*pOrigEdge, SeqOfSubsSeqOfEdges(i).UnionEdges); theContext->Remove(SeqOfSubsSeqOfEdges(i).SeqsEdges(j)); } } @@ -1107,7 +1109,9 @@ static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, //======================================================================= ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain() - : myUnifyFaces (Standard_True), + : myLinTol(Precision::Confusion()), + myAngTol(Precision::Angular()), + myUnifyFaces(Standard_True), myUnifyEdges (Standard_True), myConcatBSplines (Standard_False), myAllowInternal (Standard_False) @@ -1125,7 +1129,9 @@ ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& a const Standard_Boolean UnifyFaces, const Standard_Boolean ConcatBSplines) : myInitShape (aShape), - myUnifyFaces (UnifyFaces), + myLinTol(Precision::Confusion()), + myAngTol(Precision::Angular()), + myUnifyFaces(UnifyFaces), myUnifyEdges (UnifyEdges), myConcatBSplines (ConcatBSplines), myAllowInternal (Standard_False), @@ -1297,7 +1303,7 @@ void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape if (IsCheckSharedEdgeOri && !CheckSharedEdgeOri(aFace, anCheckedFace, edge) ) continue; - if (IsSameDomain(aFace,anCheckedFace)) { + if (IsSameDomain(aFace,anCheckedFace, myLinTol, myAngTol)) { // hotfix for 27271: prevent merging along periodic direction. if (IsLikeSeam(edge, aFace, aBaseSurface)) diff --git a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx index de185b65ce..8286e9215d 100644 --- a/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx +++ b/src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.hxx @@ -62,7 +62,19 @@ public: //! topology. Without this flag merging through multi connected edge //! is forbidden. Default value is false. Standard_EXPORT void AllowInternalEdges (const Standard_Boolean theValue); - + + //! Sets the linear tolerance. Default value is Precision::Confusion(). + void SetLinearTolerance(const Standard_Real theValue) + { + myLinTol = theValue; + } + + //! Sets the angular tolerance. Default value is Precision::Angular(). + void SetAngularTolerance(const Standard_Real theValue) + { + myAngTol = theValue; + } + //! Builds the resulting shape Standard_EXPORT void Build(); @@ -100,6 +112,8 @@ private: Standard_Boolean IsCheckSharedEdgeOri); TopoDS_Shape myInitShape; + Standard_Real myLinTol; + Standard_Real myAngTol; Standard_Boolean myUnifyFaces; Standard_Boolean myUnifyEdges; Standard_Boolean myConcatBSplines; diff --git a/tests/bugs/heal/bug27729 b/tests/bugs/heal/bug27729 new file mode 100644 index 0000000000..ea65fa6b05 --- /dev/null +++ b/tests/bugs/heal/bug27729 @@ -0,0 +1,18 @@ +puts "========" +puts "OCC27729" +puts "========" +puts "" +####################################################################### +# UnifySameDomain: allow the user to specify linear and angular tolerances +####################################################################### + +restore [locate_data_file bug27729_a_1275.brep] a + +unifysamedom r a -t 0.1 -a 0.08 + +regexp {FACE *: *(\d*)} [nbshapes r] full nbfaces +if {$nbfaces > 1000} { + puts "Error: number of faces in the result is too large" +} + +checkview -display r -2d -path ${imagedir}/${test_image}.png \ No newline at end of file