From 2ba9eb30597eeef40af20e9f9b1e85eec83f2dac Mon Sep 17 00:00:00 2001 From: msv Date: Fri, 29 Jul 2016 18:23:57 +0300 Subject: [PATCH] 0027729: UnifySameDomain: allow the user to specify linear and angular tolerances - New methods SetLinearTolerance and SetAngularTolerance have been added in the class ShapeUpgrade_UnifySameDomain. - The algorithm has been modified to consider these tolerances when checking if two faces are same domain. - The draw command unifysamedomain has been changed to accept new parameters. - The internal method MergeSeq has been changed to avoid exception connected with access to unknown key in the data map. Create test case Small correction of test case for issue CR27729 --- src/SWDRAW/SWDRAW_ShapeUpgrade.cxx | 32 +++++++--- .../ShapeUpgrade_UnifySameDomain.cxx | 62 ++++++++++--------- .../ShapeUpgrade_UnifySameDomain.hxx | 16 ++++- tests/bugs/heal/bug27729 | 18 ++++++ 4 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 tests/bugs/heal/bug27729 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