From 46e1f9caf62d5165e9189a552dd511559e972d8b Mon Sep 17 00:00:00 2001 From: lucasjerome Date: Fri, 5 Feb 2021 16:13:20 +0100 Subject: [PATCH] Remove param "precise" in BoundingBox feature and modif unit test and example --- .../FeaturesPlugin_BoundingBox.cpp | 11 +- .../FeaturesPlugin_BoundingBox.h | 2 +- .../FeaturesPlugin_CreateBoundingBox.cpp | 11 +- .../FeaturesPlugin_CreateBoundingBox.h | 2 +- src/FeaturesPlugin/Test/TestBoundingBox.py | 13 +- .../doc/examples/create_bounding_box.py | 7 +- src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp | 311 +----------------- src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h | 2 - 8 files changed, 32 insertions(+), 327 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp b/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp index 6e30b6f54..928d1c492 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.cpp @@ -74,7 +74,8 @@ void FeaturesPlugin_BoundingBox::initAttributes() //================================================================================================= void FeaturesPlugin_BoundingBox::execute() { - updateValues(); + if (!updateValues()) + return; createBoxByTwoPoints(); if (boolean(CREATEBOX_ID())->value()) { @@ -108,7 +109,7 @@ AttributePtr FeaturesPlugin_BoundingBox::attributResultValues() } //================================================================================================= -void FeaturesPlugin_BoundingBox::updateValues() +bool FeaturesPlugin_BoundingBox::updateValues() { AttributeSelectionPtr aSelection = selection(OBJECT_ID()); if (aSelection->isInitialized()) { @@ -132,12 +133,13 @@ void FeaturesPlugin_BoundingBox::updateValues() double aXmin, aXmax, aYmin,aYmax,aZmin,aZmax; std::string aError; if (!GetBoundingBox(aShape, - true, aXmin, aXmax, aYmin,aYmax, aZmin,aZmax, - aError)) + aError)) { setError("Error in bounding box calculation :" + aError); + return false; + } myShape = aShape; streamxmin << std::setprecision(14) << aXmin; @@ -160,6 +162,7 @@ void FeaturesPlugin_BoundingBox::updateValues() string(Z_MAX_COORD_ID() )->setValue( "Z = " + streamzmax.str() ); } } + return true; } //================================================================================================= diff --git a/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h b/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h index ef12a579f..e81dacef8 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h +++ b/src/FeaturesPlugin/FeaturesPlugin_BoundingBox.h @@ -126,7 +126,7 @@ private: virtual AttributePtr attributResultValues(); /// Update values displayed. - void updateValues(); + bool updateValues(); /// Create Box void createBox(); /// Update Box diff --git a/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp b/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp index f59d98b94..b8c4111a9 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.cpp @@ -73,7 +73,8 @@ void FeaturesPlugin_CreateBoundingBox::initAttributes() //================================================================================================= void FeaturesPlugin_CreateBoundingBox::execute() { - updateValues(); + if (!updateValues()) + return; createBoxByTwoPoints(); } @@ -83,7 +84,7 @@ void FeaturesPlugin_CreateBoundingBox::attributeChanged(const std::string& theID } //================================================================================================= -void FeaturesPlugin_CreateBoundingBox::updateValues() +bool FeaturesPlugin_CreateBoundingBox::updateValues() { AttributeSelectionPtr aSelection = selection(OBJECT_ID()); AttributeDoubleArrayPtr aValues = @@ -114,12 +115,13 @@ void FeaturesPlugin_CreateBoundingBox::updateValues() double aXmin, aXmax, aYmin,aYmax,aZmin,aZmax; std::string aError; if (!GetBoundingBox(aShape, - true, aXmin, aXmax, aYmin,aYmax, aZmin,aZmax, - aError)) + aError)) { setError("Error in bounding box calculation :" + aError); + return false; + } myShape = aShape; streamxmin << std::setprecision(14) << aXmin; aValues->setValue(0, aXmin); @@ -149,6 +151,7 @@ void FeaturesPlugin_CreateBoundingBox::updateValues() string(Y_MAX_COORD_ID() )->setValue( "Y = " + streamymax.str() ); string(Z_MAX_COORD_ID() )->setValue( "Z = " + streamzmax.str() ); } + return true; } //================================================================================================= diff --git a/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h b/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h index 6884ac0db..be797af76 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h +++ b/src/FeaturesPlugin/FeaturesPlugin_CreateBoundingBox.h @@ -123,7 +123,7 @@ public: private: /// Update values displayed. - void updateValues(); + bool updateValues(); }; diff --git a/src/FeaturesPlugin/Test/TestBoundingBox.py b/src/FeaturesPlugin/Test/TestBoundingBox.py index 673445e86..49f90f8e0 100644 --- a/src/FeaturesPlugin/Test/TestBoundingBox.py +++ b/src/FeaturesPlugin/Test/TestBoundingBox.py @@ -41,14 +41,15 @@ __updated__ = "2020-11-12" def test_Bounding_Box(): model.begin() - file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Step","screw.step") partSet = model.moduleDocument() Part_1 = model.addPart(partSet) Part_1_doc = Part_1.document() - Import_1 = model.addImport(Part_1_doc,file_path) + ### Create Cone + Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10) + model.do() ### Create BoundingBox - BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "screw_1")) + BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "Cone_1_1")) model.end() myDelta = 1e-6 @@ -59,15 +60,15 @@ def test_Bounding_Box(): print(" Surface area: ", Props[1]) print(" Volume : ", Props[2]) - aReflength = 0.32855301948678 + aReflength = 200 aReslength = Props[0] assert (math.fabs(aReslength - aReflength) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aReflength, aReslength) - aRefSurface = 0.0041640657342782 + aRefSurface = 1600 aResSurface = Props[1] assert (math.fabs(aResSurface - aRefSurface) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aRefSurface, aResSurface) - aRefVolume = 1.6785355394103e-05 + aRefVolume = 4000 aResVolume = Props[2] assert (math.fabs(aResVolume - aRefVolume) < myDelta), "The volume is wrong: expected = {0}, real = {1}".format(aRefVolume, aResVolume) diff --git a/src/FeaturesPlugin/doc/examples/create_bounding_box.py b/src/FeaturesPlugin/doc/examples/create_bounding_box.py index d904006ae..fa14ebaf2 100644 --- a/src/FeaturesPlugin/doc/examples/create_bounding_box.py +++ b/src/FeaturesPlugin/doc/examples/create_bounding_box.py @@ -2,12 +2,13 @@ from salome.shaper import model import os model.begin() -file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Step","screw.step") partSet = model.moduleDocument() Part_1 = model.addPart(partSet) Part_1_doc = Part_1.document() -Import_1 = model.addImport(Part_1_doc,file_path) +### Create Cone +Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10) + model.do() ### Create BoundingBox -BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "screw_1")) +BoundingBox_1 = model.getBoundingBox(Part_1_doc, model.selection("SOLID", "Cone_1_1")) model.end() diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp index 856b2eb4d..47c9417b1 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.cpp @@ -41,309 +41,8 @@ #include #include -/** -* This function constructs and returns modified shape from the original one -* for singular cases. It is used for the method GetMinDistanceSingular. -* -* \param theShape the original shape -* \param theModifiedShape output parameter. The modified shape. -* \param theAddDist output parameter. The added distance for modified shape. -* \retval true if the shape is modified; false otherwise. -* -* \internal -*/ -Standard_Boolean ModifyShape(const TopoDS_Shape &theShape, - TopoDS_Shape &theModifiedShape, - Standard_Real &theAddDist) -{ - TopExp_Explorer anExp; - int nbf = 0; - - theAddDist = 0.; - theModifiedShape.Nullify(); - - for ( anExp.Init( theShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { - nbf++; - theModifiedShape = anExp.Current(); - } - if(nbf==1) { - TopoDS_Shape sh = theShape; - while(sh.ShapeType()==TopAbs_COMPOUND) { - TopoDS_Iterator it(sh); - sh = it.Value(); - } - Handle(Geom_Surface) S = BRep_Tool::Surface(TopoDS::Face(theModifiedShape)); - if(S->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) || - S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)) || - S->IsUPeriodic()) { - const Standard_Boolean isShell = - (sh.ShapeType()==TopAbs_SHELL || sh.ShapeType()==TopAbs_FACE); - - if (!isShell && S->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) { - Handle(Geom_SphericalSurface) SS = Handle(Geom_SphericalSurface)::DownCast(S); - gp_Pnt PC = SS->Location(); - BRep_Builder B; - TopoDS_Vertex V; - B.MakeVertex(V,PC,1.e-7); - theModifiedShape = V; - theAddDist = SS->Radius(); - return Standard_True; - } - if (!isShell && S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) { - Handle(Geom_ToroidalSurface) TS = Handle(Geom_ToroidalSurface)::DownCast(S); - gp_Ax3 ax3 = TS->Position(); - Handle(Geom_Circle) C = new Geom_Circle(ax3.Ax2(),TS->MajorRadius()); - BRep_Builder B; - TopoDS_Edge E; - B.MakeEdge(E,C,1.e-7); - theModifiedShape = E; - theAddDist = TS->MinorRadius(); - return Standard_True; - } - - // non solid case or any periodic surface (Mantis 22454). - double U1,U2,V1,V2; - // changes for 0020677: EDF 1219 GEOM: MinDistance gives 0 instead of 20.88 - //S->Bounds(U1,U2,V1,V2); changed by - ShapeAnalysis::GetFaceUVBounds(TopoDS::Face(theModifiedShape),U1,U2,V1,V2); - // end of changes for 020677 (dmv) - Handle(Geom_RectangularTrimmedSurface) TrS1 = - new Geom_RectangularTrimmedSurface(S,U1,(U1+U2)/2.,V1,V2); - Handle(Geom_RectangularTrimmedSurface) TrS2 = - new Geom_RectangularTrimmedSurface(S,(U1+U2)/2.,U2,V1,V2); - TopoDS_Shape aMShape; - - TopoDS_Face F1 = BRepBuilderAPI_MakeFace(TrS1, Precision::Confusion()); - TopoDS_Face F2 = BRepBuilderAPI_MakeFace(TrS2, Precision::Confusion()); - - if (isShell) { - BRep_Builder B; - B.MakeCompound(TopoDS::Compound(aMShape)); - B.Add(aMShape, F1); - B.Add(aMShape, F2); - } else { - // The original shape is a solid. - BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0); - aSewing.Add(F1); - aSewing.Add(F2); - aSewing.Perform(); - aMShape = aSewing.SewedShape(); - BRep_Builder B; - TopoDS_Solid aSolid; - B.MakeSolid(aSolid); - B.Add(aSolid, aMShape); - aMShape = aSolid; - } - - Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; - sfs->Init(aMShape); - sfs->SetPrecision(1.e-6); - sfs->SetMaxTolerance(1.0); - sfs->Perform(); - theModifiedShape = sfs->Shape(); - return Standard_True; - } - } - - theModifiedShape = theShape; - return Standard_False; - } - -//======================================================================= -// function : GetMinDistanceSingular -//======================================================================= -double GetMinDistanceSingular(const TopoDS_Shape& aSh1, - const TopoDS_Shape& aSh2, - gp_Pnt& Ptmp1, gp_Pnt& Ptmp2) -{ - TopoDS_Shape tmpSh1; - TopoDS_Shape tmpSh2; - Standard_Real AddDist1 = 0.; - Standard_Real AddDist2 = 0.; - Standard_Boolean IsChange1 = ModifyShape(aSh1, tmpSh1, AddDist1); - Standard_Boolean IsChange2 = ModifyShape(aSh2, tmpSh2, AddDist2); - - if( !IsChange1 && !IsChange2 ) - return -2.0; - - BRepExtrema_DistShapeShape dst(tmpSh1,tmpSh2); - if (dst.IsDone()) { - double MinDist = 1.e9; - gp_Pnt PMin1, PMin2, P1, P2; - for (int i = 1; i <= dst.NbSolution(); i++) { - P1 = dst.PointOnShape1(i); - P2 = dst.PointOnShape2(i); - Standard_Real Dist = P1.Distance(P2); - if (MinDist > Dist) { - MinDist = Dist; - PMin1 = P1; - PMin2 = P2; - } - } - if(MinDist<1.e-7) { - Ptmp1 = PMin1; - Ptmp2 = PMin2; - } - else { - gp_Dir aDir(gp_Vec(PMin1,PMin2)); - if( MinDist > (AddDist1+AddDist2) ) { - Ptmp1 = gp_Pnt(PMin1.X() + aDir.X()*AddDist1, - PMin1.Y() + aDir.Y()*AddDist1, - PMin1.Z() + aDir.Z()*AddDist1); - Ptmp2 = gp_Pnt(PMin2.X() - aDir.X()*AddDist2, - PMin2.Y() - aDir.Y()*AddDist2, - PMin2.Z() - aDir.Z()*AddDist2); - return (MinDist - AddDist1 - AddDist2); - } - else { - if( AddDist1 > 0 ) { - Ptmp1 = gp_Pnt(PMin1.X() + aDir.X()*AddDist1, - PMin1.Y() + aDir.Y()*AddDist1, - PMin1.Z() + aDir.Z()*AddDist1); - Ptmp2 = Ptmp1; - } - else { - Ptmp2 = gp_Pnt(PMin2.X() - aDir.X()*AddDist2, - PMin2.Y() - aDir.Y()*AddDist2, - PMin2.Z() - aDir.Z()*AddDist2); - Ptmp1 = Ptmp2; - } - } - } - double res = MinDist - AddDist1 - AddDist2; - if(res<0.) res = 0.0; - return res; - } - return -2.0; -} - -//======================================================================= -// function : GetMinDistance -//======================================================================= -Standard_Real GetMinDistance(const TopoDS_Shape& theShape1, - const TopoDS_Shape& theShape2, - gp_Pnt& thePnt1, gp_Pnt& thePnt2) -{ - Standard_Real aResult = 1.e9; - - // Issue 0020231: A min distance bug with torus and vertex. - // Make GetMinDistance() return zero if a sole VERTEX is inside any of SOLIDs - - // which of shapes consists of only one vertex? - TopExp_Explorer exp1(theShape1,TopAbs_VERTEX), exp2(theShape2,TopAbs_VERTEX); - TopoDS_Shape V1 = exp1.More() ? exp1.Current() : TopoDS_Shape(); - TopoDS_Shape V2 = exp2.More() ? exp2.Current() : TopoDS_Shape(); - exp1.Next(); exp2.Next(); - if ( exp1.More() ) V1.Nullify(); - if ( exp2.More() ) V2.Nullify(); - // vertex and container of solids - TopoDS_Shape V = V1.IsNull() ? V2 : V1; - TopoDS_Shape S = V1.IsNull() ? theShape1 : theShape2; - if ( !V.IsNull() ) { - // classify vertex against solids - gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( V ) ); - for ( exp1.Init( S, TopAbs_SOLID ); exp1.More(); exp1.Next() ) { - BRepClass3d_SolidClassifier classifier( exp1.Current(), p, 1e-6); - if ( classifier.State() == TopAbs_IN ) { - thePnt1 = p; - thePnt2 = p; - return 0.0; - } - } - } - - aResult = GetMinDistanceSingular(theShape1, theShape2, thePnt1, thePnt2); - - - BRepExtrema_DistShapeShape dst (theShape1, theShape2); - if (dst.IsDone()) { - gp_Pnt P1, P2; - - for (int i = 1; i <= dst.NbSolution(); i++) { - P1 = dst.PointOnShape1(i); - P2 = dst.PointOnShape2(i); - - Standard_Real Dist = P1.Distance(P2); - if (aResult < 0 || aResult > Dist) { - aResult = Dist; - thePnt1 = P1; - thePnt2 = P2; - } - } - } - - return aResult; -} - -//======================================================================= -// function : PreciseBoundingBox -//======================================================================= -Standard_Boolean PreciseBoundingBox - (const TopoDS_Shape &theShape, Bnd_Box &theBox) -{ - if (theBox.IsVoid()) BRepBndLib::Add( theShape, theBox ); - if (theBox.IsVoid()) return Standard_False; - - Standard_Real aBound[6]; - theBox.Get(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]); - - Standard_Integer i; - const gp_Pnt aMid(0.5*(aBound[1] + aBound[0]), // XMid - 0.5*(aBound[3] + aBound[2]), // YMid - 0.5*(aBound[5] + aBound[4])); // ZMid - const gp_XYZ aSize(aBound[1] - aBound[0], // DX - aBound[3] - aBound[2], // DY - aBound[5] - aBound[4]); // DZ - const gp_Pnt aPnt[6] = - { - gp_Pnt(aBound[0] - (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMin - gp_Pnt(aBound[1] + (aBound[1] - aBound[0]), aMid.Y(), aMid.Z()), // XMax - gp_Pnt(aMid.X(), aBound[2] - (aBound[3] - aBound[2]), aMid.Z()), // YMin - gp_Pnt(aMid.X(), aBound[3] + (aBound[3] - aBound[2]), aMid.Z()), // YMax - gp_Pnt(aMid.X(), aMid.Y(), aBound[4] - (aBound[5] - aBound[4])), // ZMin - gp_Pnt(aMid.X(), aMid.Y(), aBound[5] + (aBound[5] - aBound[4])) // ZMax - }; - const gp_Dir aDir[3] = { gp::DX(), gp::DY(), gp::DZ() }; - const Standard_Real aPlnSize[3] = - { - 0.5*Max(aSize.Y(), aSize.Z()), // XMin, XMax planes - 0.5*Max(aSize.X(), aSize.Z()), // YMin, YMax planes - 0.5*Max(aSize.X(), aSize.Y()) // ZMin, ZMax planes - }; - gp_Pnt aPMin[2]; - - for (i = 0; i < 6; i++) { - const Standard_Integer iHalf = i/2; - const gp_Pln aPln(aPnt[i], aDir[iHalf]); - BRepBuilderAPI_MakeFace aMkFace(aPln, -aPlnSize[iHalf], aPlnSize[iHalf], - -aPlnSize[iHalf], aPlnSize[iHalf]); - - if (!aMkFace.IsDone()) { - return Standard_False; - } - - TopoDS_Shape aFace = aMkFace.Shape(); - - // Get minimal distance between planar face and shape. - Standard_Real aMinDist = GetMinDistance(aFace, theShape, aPMin[0], aPMin[1]); - - if (aMinDist < 0.) { - return Standard_False; - } - - aBound[i] = aPMin[1].Coord(iHalf + 1); - } - - // Update Bounding box with the new values. - theBox.SetVoid(); - theBox.Update(aBound[0], aBound[2], aBound[4], aBound[1], aBound[3], aBound[5]); - - return Standard_True; -} - //================================================================================================= bool GetBoundingBox(const std::shared_ptr& theShape, - const bool thePrecise, Standard_Real& theXmin,Standard_Real& theXmax, Standard_Real& theYmin,Standard_Real& theYmax, Standard_Real& theZmin,Standard_Real& theZmax, @@ -375,13 +74,13 @@ bool GetBoundingBox(const std::shared_ptr& theShape, // remove triangulation to obtain more exact boundaries BRepTools::Clean(aShape); - BRepBndLib::Add(aShape, B); + BRepBndLib::AddOptimal(aShape, B); - if (thePrecise) { - if (!PreciseBoundingBox(aShape, B)) { - theError = "GetBoundingBox Error: Bounding box cannot be precised"; + if (B.IsXThin(Precision::Confusion()) + || B.IsYThin(Precision::Confusion()) + || B.IsZThin(Precision::Confusion())) { + theError = "GetBoundingBox Error: Bounding box cannot be precised"; return false; - } } B.Get(theXmin, theYmin, theZmin, theXmax, theYmax, theZmax); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h b/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h index 010c3a30b..84a8dc3a5 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_BoundingBox.h @@ -26,7 +26,6 @@ /// get the boundin box of theshape. /// \param theShape the shape - /// \param thePrecise precise TRUE for precise computation; FALSE for fast one. /// \param theXmin X min of the box /// \param theXmax X max of the box /// \param theYmin Y min of the box @@ -36,7 +35,6 @@ /// \param theError error GEOMALGOAPI_EXPORT bool GetBoundingBox(const std::shared_ptr& theShape, - const bool thePrecise, Standard_Real& theXmin,Standard_Real& theXmax, Standard_Real& theYmin,Standard_Real& theYmax, Standard_Real& theZmin,Standard_Real& theZmax, -- 2.39.2