From b609dcabc28d2e551672e4a94118536e2e7876bc Mon Sep 17 00:00:00 2001 From: emv Date: Thu, 8 Dec 2016 16:49:29 +0300 Subject: [PATCH] 0027878: Development of the Gluing operations based on the new Boolean component The Gluing operation is an additional option for the algorithms in the Boolean Component such as General Fuse, Boolean operations, Section operation, Maker Volume and Cells Builder algorithms. The Gluing options have been designed to speed up the computation of the interference among arguments of the operations on special cases, in which the arguments may be overlapping but do not have real intersections between their sub-shapes. This option cannot be used on the shapes having real intersections, like intersection vertex between edges, or intersection vertex between edge and a face or intersection line between faces. The Gluing option is an enumeration implemented in BOPAlgo_GlueEnum.hxx. There are following items in the enum: * BOPAlgo_GlueOff - default value for the algorithms, Gluing is switched off; * BOPAlgo_GlueShift - Glue option for shapes with partial coincidence; * BOPAlgo_GlueFull - Glue option for shapes with full coincidence. For setting the Gluing options for the algorithm it is just necessary to call the SetGlue(BOPAlgo_GlueEnum) method with appropriate Glue value. For using this option in DRAW the command bglue has been implemented: * 0 - default value, Gluing is off; * 1 - for partial coincidence; * 2 - for full coincidence Elimination of the warnings. --- .../boolean_operations/boolean_operations.md | 75 +++++++- .../images/glue_options_image001.PNG | Bin 0 -> 4362 bytes .../images/glue_options_image002.PNG | Bin 0 -> 3474 bytes .../images/glue_options_image003.PNG | Bin 0 -> 4708 bytes .../images/glue_options_image004.PNG | Bin 0 -> 12628 bytes .../images/glue_options_image005.PNG | Bin 0 -> 19193 bytes src/BOPAlgo/BOPAlgo_BOP.cxx | 1 + src/BOPAlgo/BOPAlgo_Builder.cxx | 24 ++- src/BOPAlgo/BOPAlgo_Builder.hxx | 7 + src/BOPAlgo/BOPAlgo_GlueEnum.hxx | 64 +++++++ src/BOPAlgo/BOPAlgo_MakerVolume.cxx | 1 + src/BOPAlgo/BOPAlgo_PaveFiller.cxx | 22 +++ src/BOPAlgo/BOPAlgo_PaveFiller.hxx | 10 + src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx | 175 ++++++++++-------- src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx | 23 ++- src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx | 46 +++-- src/BOPAlgo/FILES | 1 + src/BOPTest/BOPTest_APICommands.cxx | 4 + src/BOPTest/BOPTest_BOPCommands.cxx | 8 + src/BOPTest/BOPTest_CellsCommands.cxx | 11 +- src/BOPTest/BOPTest_Objects.cxx | 26 +++ src/BOPTest/BOPTest_Objects.hxx | 4 + src/BOPTest/BOPTest_OptionCommands.cxx | 37 +++- src/BOPTest/BOPTest_PartitionCommands.cxx | 4 +- .../BRepAlgoAPI_BooleanOperation.cxx | 1 + src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx | 23 ++- src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.hxx | 8 + tests/bugs/modalg_6/bug27878_1 | 24 +++ tests/bugs/modalg_6/bug27878_2 | 24 +++ tests/bugs/modalg_6/bug27878_3 | 24 +++ tests/bugs/modalg_6/bug27878_4 | 24 +++ tests/bugs/modalg_6/bug27878_5 | 26 +++ tests/bugs/modalg_6/bug27878_6 | 46 +++++ 33 files changed, 628 insertions(+), 115 deletions(-) create mode 100644 dox/user_guides/boolean_operations/images/glue_options_image001.PNG create mode 100644 dox/user_guides/boolean_operations/images/glue_options_image002.PNG create mode 100644 dox/user_guides/boolean_operations/images/glue_options_image003.PNG create mode 100644 dox/user_guides/boolean_operations/images/glue_options_image004.PNG create mode 100644 dox/user_guides/boolean_operations/images/glue_options_image005.PNG create mode 100644 src/BOPAlgo/BOPAlgo_GlueEnum.hxx create mode 100644 tests/bugs/modalg_6/bug27878_1 create mode 100644 tests/bugs/modalg_6/bug27878_2 create mode 100644 tests/bugs/modalg_6/bug27878_3 create mode 100644 tests/bugs/modalg_6/bug27878_4 create mode 100644 tests/bugs/modalg_6/bug27878_5 create mode 100644 tests/bugs/modalg_6/bug27878_6 diff --git a/dox/user_guides/boolean_operations/boolean_operations.md b/dox/user_guides/boolean_operations/boolean_operations.md index 356ef59996..590332e1d9 100644 --- a/dox/user_guides/boolean_operations/boolean_operations.md +++ b/dox/user_guides/boolean_operations/boolean_operations.md @@ -2100,10 +2100,10 @@ With the Fuzzy option it is possible to get the expected result -- it is just ne Fuzzy option is included in interface of Intersection Part (class *BOPAlgo_PaveFiller*) and application programming interface (class *BRepAlgoAPI_BooleanOperation*) -@subsection occt_algorithms_11a_2 Examples +@subsubsection occt_algorithms_11a_1_1 Examples The following examples demonstrate the advantages of usage Fuzzy option operations over the Basic Operations in typical situations. -@subsubsection occt_algorithms_11a_1_1 Case 1 +#### Case 1 In this example the cylinder (shown in yellow and transparent) is subtracted from the box (shown in red). The cylinder is shifted by 5e-5 relatively to the box along its axis (the distance between rear faces of the box and cylinder is 5e-5). @@ -2117,7 +2117,7 @@ The following results are obtained using Basic Operations and the Fuzzy ones wit In this example Fuzzy option allows eliminating a very thin part of the result shape produced by Basic algorithm due to misalignment of rear faces of the box and the cylinder. -@subsubsection occt_algorithms_11a_1_2 Case 2 +#### Case 2 In this example two boxes are fused. One of them has dimensions 10*10*10, and the other is 10*10.000001*10.000001 and adjacent to the first one. There is no gap in this case as the surfaces of the neighboring faces coincide, but one box is slightly greater than the other. @@ -2131,7 +2131,7 @@ The following results are obtained using Basic Operations and the Fuzzy ones wit In this example Fuzzy option allows eliminating an extremely narrow face in the result produced by Basic operation. -@subsubsection occt_algorithms_11a_1_3 Case 3 +#### Case 3 In this example the small planar face (shown in orange) is subtracted from the big one (shown in yellow). There is a gap 1e-5 between the edges of these faces. @@ -2145,7 +2145,7 @@ The following results are obtained using Basic Operations and the Fuzzy ones wit In this example Fuzzy options eliminated a pin-like protrusion resulting from the gap between edges of the argument faces. -@subsubsection occt_algorithms_11a_1_4 Case 4 +#### Case 4 In this example the small edge is subtracted from the big one. The edges are overlapping not precisely, with max deviation between them equal to 5.28004e-5. We will use 6e-5 value for Fuzzy option. @@ -2159,6 +2159,71 @@ The following results are obtained using Basic Operations and the Fuzzy ones wit This example stresses not only the validity, but also the performance issue. The usage of Fuzzy option with the appropriate value allows processing the case much faster than with the pure Basic operation. The performance gain for the case is 45 (Processor: Intel(R) Core(TM) i5-3450 CPU @ 3.10 GHz). +@subsection occt_algorithms_11a_2 Gluing Operation + +The Gluing operation is the option of the Basic Operations, such as General Fuse, Boolean and Section operations. +It has been designed to speed up the computation of the interferences among arguments of the operations on special cases, in which the arguments may be overlapping but do not have real intersections between their sub-shapes. + +This option cannot be used on the shapes having real intersections, like intersection vertex between edges, or intersection vertex between edge and a face or intersection line between faces: +@figure{/user_guides/boolean_operations/images/glue_options_image002.png, "Intersecting faces"} + +There are two possibilities of overlapping shapes: +* The shapes can be partially coinciding - the faces do not have intersection curves, but overlapping. The faces of such arguments will be split during the operation. The following picture illustrates such shapes: +@figure{/user_guides/boolean_operations/images/glue_options_image001.png, "Partially coinciding faces"} +* The shapes can be fully coinciding - there should be no partial overlapping of the faces, thus no intersection of type EDGE/FACE at all. In such cases the faces will not be split during the operation +@figure{/user_guides/boolean_operations/images/glue_options_image003.png, "Full coinciding faces of the boxes"} + +Thus, there are two possible options - for full and partial coincidence of the shapes. + +Even though there are no real intersections on such cases without Gluing options the algorithm will still intersect the sub-shapes of the arguments with interfering bounding boxes. + +The performance improvement in gluing mode is achieved by excluding the most time consuming computations and in some case can go up to 90%: +* Exclude computation of FACE/FACE intersections for partial coincidence; +* Exclude computation of VERTEX/FACE, EDGE/FACE and FACE/FACE intersections for full coincidence. + +By setting the Gluing option for the operation user should guarantee that the arguments are really coinciding. The algorithm does not check this itself. Setting inappropriate option for the operation is likely to lead to incorrect result. + +@subsubsection occt_algorithms_11a_2_1 Usage + +The Gluing option is an enumeration implemented in BOPAlgo_GlueEnum.hxx: +* BOPAlgo_GlueOff - default value for the algorithms, Gluing is switched off; +* BOPAlgo_GlueShift - Glue option for shapes with partial coincidence; +* BOPAlgo_GlueFull - Glue option for shapes with full coincidence. + +#### API level +For setting the Gluing options for the algorithm it is just necessary to call the SetGlue(const BOPAlgo_Glue) method with appropriate value: +~~~~ +BOPAlgo_Builder aGF; +// +.... +// setting the gluing option to speed up intersection of the arguments +aGF.SetGlue(BOPAlgo_GlueShift) +// +.... +~~~~ + +#### TCL level +For setting the Gluing options in DRAW it is necessary to call the bglue command with appropriate value: +* 0 - default value, Gluing is off; +* 1 - for partial coincidence; +* 2 - for full coincidence + +~~~~ +bglue 1 +~~~~ + +@subsubsection occt_algorithms_11a_2_2 Examples +#### Case1 - Fusing the 64 bspline boxes into one solid +@figure{/user_guides/boolean_operations/images/glue_options_image004.png, "BSpline Boxes with partial coincidence"} + +Performance improvement from using the GlueShift option in this case is about 70 percent. + +#### Case2 - Sewing faces of the shape after reading from IGES +@figure{/user_guides/boolean_operations/images/glue_options_image005.png, "Faces with coinciding but not shared edges"} + +Performance improvement in this case is also about 70 percent. + + @section occt_algorithms_11b Usage The chapter contains some examples of the OCCT Boolean Component usage. The usage is possible on two levels: C++ and Tcl. diff --git a/dox/user_guides/boolean_operations/images/glue_options_image001.PNG b/dox/user_guides/boolean_operations/images/glue_options_image001.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a8287ef3e3135f7cb6d7aa98170f136e35cf9763 GIT binary patch literal 4362 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 kb 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 literal 0 HcmV?d00001 diff --git a/src/BOPAlgo/BOPAlgo_BOP.cxx b/src/BOPAlgo/BOPAlgo_BOP.cxx index aec1a456a5..932877185a 100644 --- a/src/BOPAlgo/BOPAlgo_BOP.cxx +++ b/src/BOPAlgo/BOPAlgo_BOP.cxx @@ -376,6 +376,7 @@ void BOPAlgo_BOP::Perform() pPF->SetProgressIndicator(myProgressIndicator); pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); + pPF->SetGlue(myGlue); // pPF->Perform(); // diff --git a/src/BOPAlgo/BOPAlgo_Builder.cxx b/src/BOPAlgo/BOPAlgo_Builder.cxx index 59e909c230..598c5c905e 100644 --- a/src/BOPAlgo/BOPAlgo_Builder.cxx +++ b/src/BOPAlgo/BOPAlgo_Builder.cxx @@ -51,7 +51,8 @@ BOPAlgo_Builder::BOPAlgo_Builder() myShapesSD(100, myAllocator), mySplits(100, myAllocator), myOrigins(100, myAllocator), - myNonDestructive(Standard_False) + myNonDestructive(Standard_False), + myGlue(BOPAlgo_GlueOff) { } //======================================================================= @@ -71,7 +72,8 @@ BOPAlgo_Builder::BOPAlgo_Builder myShapesSD(100, myAllocator), mySplits(100, myAllocator), myOrigins(100, myAllocator), - myNonDestructive(Standard_False) + myNonDestructive(Standard_False), + myGlue(BOPAlgo_GlueOff) { } //======================================================================= @@ -200,6 +202,22 @@ Standard_Boolean BOPAlgo_Builder::NonDestructive() const return myNonDestructive; } //======================================================================= +//function : SetGlue +//purpose : +//======================================================================= +void BOPAlgo_Builder::SetGlue(const BOPAlgo_GlueEnum theGlue) +{ + myGlue=theGlue; +} +//======================================================================= +//function : Glue +//purpose : +//======================================================================= +BOPAlgo_GlueEnum BOPAlgo_Builder::Glue() const +{ + return myGlue; +} +//======================================================================= // function: CheckData // purpose: //======================================================================= @@ -268,6 +286,7 @@ void BOPAlgo_Builder::Perform() pPF->SetProgressIndicator(myProgressIndicator); pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); + pPF->SetGlue(myGlue); // pPF->Perform(); // @@ -283,6 +302,7 @@ void BOPAlgo_Builder::PerformWithFiller(const BOPAlgo_PaveFiller& theFiller) myEntryPoint=0; myNonDestructive = theFiller.NonDestructive(); myFuzzyValue = theFiller.FuzzyValue(); + myGlue = theFiller.Glue(); PerformInternal(theFiller); } //======================================================================= diff --git a/src/BOPAlgo/BOPAlgo_Builder.hxx b/src/BOPAlgo/BOPAlgo_Builder.hxx index 238aa17203..0323b854a1 100644 --- a/src/BOPAlgo/BOPAlgo_Builder.hxx +++ b/src/BOPAlgo/BOPAlgo_Builder.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,11 @@ Standard_EXPORT virtual ~BOPAlgo_Builder(); //! a copy of a sub-shape is created in the result if it is needed to be updated. Standard_EXPORT Standard_Boolean NonDestructive() const; + //! Sets the glue option for the algorithm + Standard_EXPORT void SetGlue(const BOPAlgo_GlueEnum theGlue); + + //! Returns the glue option of the algorithm + Standard_EXPORT BOPAlgo_GlueEnum Glue() const; protected: @@ -167,6 +173,7 @@ protected: BOPCol_DataMapOfShapeListOfShape mySplits; BOPCol_DataMapOfShapeShape myOrigins; Standard_Boolean myNonDestructive; + BOPAlgo_GlueEnum myGlue; private: diff --git a/src/BOPAlgo/BOPAlgo_GlueEnum.hxx b/src/BOPAlgo/BOPAlgo_GlueEnum.hxx new file mode 100644 index 0000000000..740e32fc10 --- /dev/null +++ b/src/BOPAlgo/BOPAlgo_GlueEnum.hxx @@ -0,0 +1,64 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BOPAlgo_GlueEnum_HeaderFile +#define _BOPAlgo_GlueEnum_HeaderFile + +//! The Enumeration describes an additional option for the algorithms +//! in the Boolean Component such as General Fuse, Boolean operations, +//! Section operation, Maker Volume and Cells Builder algorithms. +//! +//! The Gluing options have been designed to speed up the computation +//! of the interference among arguments of the operations on special cases, +//! in which the arguments may be overlapping but do not have real intersections +//! between their sub-shapes. +//! +//! This option cannot be used on the shapes having real intersections, +//! like intersection vertex between edges, or intersection vertex between +//! edge and a face or intersection line between faces. +//! +//! There are two possibilities of overlapping shapes: +//! 1. The shapes can be partially coinciding - the faces do not have +//! intersection curves, but overlapping. The faces of such arguments will +//! be split during the operation; +//! 2. The shapes can be fully coinciding - there should be no partial +//! overlapping of the faces, thus no intersection of type EDGE/FACE at all. +//! In such cases the faces will not be split during the operation. +//! +//! Even though there are no real intersections on such cases without Gluing options the algorithm +//! will still intersect the sub-shapes of the arguments with interfering bounding boxes. +//! +//! The performance improvement in gluing mode is achieved by excluding +//! the most time consuming computations according to the given Gluing parameter: +//! 1. Computation of FACE/FACE intersections for partial coincidence; +//! 2. And computation of VERTEX/FACE, EDGE/FACE and FACE/FACE intersections for full coincidence. +//! +//! By setting the Gluing option for the operation user should guarantee +//! that the arguments are really coinciding. The algorithms do not check this itself. +//! Setting inappropriate option for the operation is likely to lead to incorrect result. +//! +//! There are following items in the enumeration: +//! BOPAlgo_GlueOff - default value for the algorithms, Gluing is switched off; +//! BOPAlgo_GlueShift - Glue option for shapes with partial coincidence; +//! BOPAlgo_GlueFull - Glue option for shapes with full coincidence. +//! + +enum BOPAlgo_GlueEnum +{ + BOPAlgo_GlueOff, + BOPAlgo_GlueShift, + BOPAlgo_GlueFull +}; + +#endif // _BOPAlgo_GlueEnum_HeaderFile diff --git a/src/BOPAlgo/BOPAlgo_MakerVolume.cxx b/src/BOPAlgo/BOPAlgo_MakerVolume.cxx index 69808488c8..a7639cc87b 100644 --- a/src/BOPAlgo/BOPAlgo_MakerVolume.cxx +++ b/src/BOPAlgo/BOPAlgo_MakerVolume.cxx @@ -101,6 +101,7 @@ void BOPAlgo_MakerVolume::Perform() pPF->SetProgressIndicator(myProgressIndicator); pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); + pPF->SetGlue(myGlue); pPF->Perform(); // myEntryPoint = 1; diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx index d20e039fe8..247a5b87be 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx @@ -43,6 +43,7 @@ BOPAlgo_PaveFiller::BOPAlgo_PaveFiller() myIterator=NULL; myNonDestructive=Standard_False; myIsPrimary=Standard_True; + myGlue=BOPAlgo_GlueOff; } //======================================================================= //function : @@ -57,6 +58,7 @@ BOPAlgo_PaveFiller::BOPAlgo_PaveFiller myIterator=NULL; myNonDestructive=Standard_False; myIsPrimary=Standard_True; + myGlue=BOPAlgo_GlueOff; } //======================================================================= //function : ~ @@ -83,6 +85,22 @@ Standard_Boolean BOPAlgo_PaveFiller::NonDestructive()const return myNonDestructive; } //======================================================================= +//function : SetGlue +//purpose : +//======================================================================= +void BOPAlgo_PaveFiller::SetGlue(const BOPAlgo_GlueEnum theGlue) +{ + myGlue=theGlue; +} +//======================================================================= +//function : Glue +//purpose : +//======================================================================= +BOPAlgo_GlueEnum BOPAlgo_PaveFiller::Glue() const +{ + return myGlue; +} +//======================================================================= //function : SetIsPrimary //purpose : //======================================================================= @@ -295,6 +313,10 @@ void BOPAlgo_PaveFiller::PerformInternal() if (myErrorStatus) { return; } + // + if (myGlue != BOPAlgo_GlueOff) { + return; + } // 03 PerformVZ(); if (myErrorStatus) { diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.hxx b/src/BOPAlgo/BOPAlgo_PaveFiller.hxx index 0b79a150da..70bcba8f4b 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.hxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.hxx @@ -48,6 +48,7 @@ #include #include #include +#include class IntTools_Context; class BOPDS_DS; class BOPAlgo_SectionAttribute; @@ -101,6 +102,14 @@ public: + //! Sets the glue option for the algorithm + Standard_EXPORT void SetGlue(const BOPAlgo_GlueEnum theGlue); + + //! Returns the glue option of the algorithm + Standard_EXPORT BOPAlgo_GlueEnum Glue() const; + + + protected: typedef NCollection_DataMap @@ -396,6 +405,7 @@ protected: BOPAlgo_SectionAttribute mySectionAttribute; Standard_Boolean myNonDestructive; Standard_Boolean myIsPrimary; + BOPAlgo_GlueEnum myGlue; private: diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx index 356a43bd9a..f9dce5eb9c 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx @@ -142,96 +142,109 @@ typedef BOPCol_ContextCnt //======================================================================= void BOPAlgo_PaveFiller::PerformVF() { - Standard_Boolean bJustAdd; - Standard_Integer iSize, nV, nF, nVSD, iFlag, nVx, aNbVF, k; - Standard_Real aT1, aT2; - BOPAlgo_VectorOfVertexFace aVVF; - // myErrorStatus=0; // myIterator->Initialize(TopAbs_VERTEX, TopAbs_FACE); - iSize=myIterator->ExpectedLength(); - if (iSize) { - // - BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF(); - aVFs.SetIncrement(iSize); - // + Standard_Integer iSize = myIterator->ExpectedLength(); + // + Standard_Boolean bJustAdd; + Standard_Integer nV, nF; + // + if (myGlue == BOPAlgo_GlueFull) { + // there is no need to intersect vertices with faces in this mode + // just initialize FaceInfo for all faces for (; myIterator->More(); myIterator->Next()) { myIterator->Value(nV, nF, bJustAdd); - if(bJustAdd) { - continue; - } - // - if (myDS->IsSubShape(nV, nF)) { - continue; - } - // - if (myDS->HasInterfShapeSubShapes(nV, nF)) { + if (!bJustAdd && !myDS->IsSubShape(nV, nF)) { myDS->ChangeFaceInfo(nF); - continue; } - // - nVx=nV; - if (myDS->HasShapeSD(nV, nVSD)) { - nVx=nVSD; - } - // - myDS->ChangeFaceInfo(nF);// ! - // - const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&myDS->Shape(nVx))); - const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF))); - // - BOPAlgo_VertexFace& aVertexFace=aVVF.Append1(); - // - aVertexFace.SetIndices(nV, nF); - aVertexFace.SetVertex(aV); - aVertexFace.SetFace(aF); - aVertexFace.SetFuzzyValue(myFuzzyValue); - aVertexFace.SetProgressIndicator(myProgressIndicator); - }//for (; myIterator->More(); myIterator->Next()) { - // - aNbVF=aVVF.Extent(); - //================================================================ - BOPAlgo_VertexFaceCnt::Perform(myRunParallel, aVVF, myContext); - //================================================================ - // - for (k=0; k < aNbVF; ++k) { - const BOPAlgo_VertexFace& aVertexFace=aVVF(k); - // - iFlag=aVertexFace.Flag(); - if (iFlag) { - continue; - } - // - aVertexFace.Indices(nV, nF); - aVertexFace.Parameters(aT1, aT2); - // 1 - BOPDS_InterfVF& aVF=aVFs.Append1(); - aVF.SetIndices(nV, nF); - aVF.SetUV(aT1, aT2); - // 2 - myDS->AddInterf(nV, nF); - // - // 3 update vertex V/F if necessary - Standard_Real aTolVNew = aVertexFace.VertexNewTolerance(); - nVx=UpdateVertex(nV, aTolVNew); - // - // 4 - if (myDS->IsNewShape(nVx)) { - aVF.SetIndexNew(nVx); - } - // 5 update FaceInfo - BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF); - BOPCol_MapOfInteger& aMVIn=aFI.ChangeVerticesIn(); - aMVIn.Add(nVx); - }//for (k=0; k < aNbVF; ++k) { - }// if (iSize) { - else { - iSize=10; - BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF(); - aVFs.SetIncrement(iSize); + } + return; } // + BOPDS_VectorOfInterfVF& aVFs = myDS->InterfVF(); + if (!iSize) { + iSize = 10; + aVFs.SetIncrement(iSize); + // + TreatVerticesEE(); + return; + } + // + Standard_Integer nVSD, iFlag, nVx, aNbVF, k; + Standard_Real aT1, aT2; + BOPAlgo_VectorOfVertexFace aVVF; + // + aVFs.SetIncrement(iSize); + // + for (; myIterator->More(); myIterator->Next()) { + myIterator->Value(nV, nF, bJustAdd); + if(bJustAdd) { + continue; + } + // + if (myDS->IsSubShape(nV, nF)) { + continue; + } + // + myDS->ChangeFaceInfo(nF); + if (myDS->HasInterfShapeSubShapes(nV, nF)) { + continue; + } + // + nVx=nV; + if (myDS->HasShapeSD(nV, nVSD)) { + nVx=nVSD; + } + // + const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&myDS->Shape(nVx))); + const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF))); + // + BOPAlgo_VertexFace& aVertexFace=aVVF.Append1(); + // + aVertexFace.SetIndices(nV, nF); + aVertexFace.SetVertex(aV); + aVertexFace.SetFace(aF); + aVertexFace.SetFuzzyValue(myFuzzyValue); + aVertexFace.SetProgressIndicator(myProgressIndicator); + }//for (; myIterator->More(); myIterator->Next()) { + // + aNbVF=aVVF.Extent(); + //================================================================ + BOPAlgo_VertexFaceCnt::Perform(myRunParallel, aVVF, myContext); + //================================================================ + // + for (k=0; k < aNbVF; ++k) { + const BOPAlgo_VertexFace& aVertexFace=aVVF(k); + // + iFlag=aVertexFace.Flag(); + if (iFlag) { + continue; + } + // + aVertexFace.Indices(nV, nF); + aVertexFace.Parameters(aT1, aT2); + // 1 + BOPDS_InterfVF& aVF=aVFs.Append1(); + aVF.SetIndices(nV, nF); + aVF.SetUV(aT1, aT2); + // 2 + myDS->AddInterf(nV, nF); + // + // 3 update vertex V/F if necessary + Standard_Real aTolVNew = aVertexFace.VertexNewTolerance(); + nVx=UpdateVertex(nV, aTolVNew); + // + // 4 + if (myDS->IsNewShape(nVx)) { + aVF.SetIndexNew(nVx); + } + // 5 update FaceInfo + BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF); + BOPCol_MapOfInteger& aMVIn=aFI.ChangeVerticesIn(); + aMVIn.Add(nVx); + }//for (k=0; k < aNbVF; ++k) { + // TreatVerticesEE(); } //======================================================================= diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx index 5715a65195..da31950f81 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx @@ -139,22 +139,35 @@ typedef BOPCol_ContextCnt //======================================================================= void BOPAlgo_PaveFiller::PerformEF() { - Standard_Integer iSize; - // myErrorStatus=0; // FillShrunkData(TopAbs_EDGE, TopAbs_FACE); // myIterator->Initialize(TopAbs_EDGE, TopAbs_FACE); - iSize=myIterator->ExpectedLength(); + Standard_Integer iSize = myIterator->ExpectedLength(); if (!iSize) { return; } // - Standard_Boolean bJustAdd, bV[2], bIsPBSplittable; + Standard_Boolean bJustAdd; + Standard_Integer nE, nF; + // + if (myGlue == BOPAlgo_GlueFull) { + // there is no need to intersect edges with faces in this mode + // just initialize FaceInfo for faces + for (; myIterator->More(); myIterator->Next()) { + myIterator->Value(nE, nF, bJustAdd); + if (!bJustAdd && !myDS->ShapeInfo(nE).HasFlag()) { + myDS->ChangeFaceInfo(nF); + } + } + return; + } + // + Standard_Boolean bV[2], bIsPBSplittable; Standard_Boolean bV1, bV2, bExpressCompute; Standard_Integer nV1, nV2; - Standard_Integer nE, nF, aDiscretize, i, aNbCPrts, iX, nV[2]; + Standard_Integer aDiscretize, i, aNbCPrts, iX, nV[2]; Standard_Integer aNbEdgeFace, k; Standard_Real aTolE, aTolF, aTS1, aTS2, aT1, aT2, aDeflection; Handle(NCollection_BaseAllocator) aAllocator; diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx index f797748c1b..1a36c188f3 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx @@ -236,22 +236,34 @@ void BOPAlgo_PaveFiller::PerformFF() // ToleranceFF(aBAS1, aBAS2, aTolFF); // - BOPAlgo_FaceFace& aFaceFace=aVFaceFace.Append1(); - // - aFaceFace.SetIndices(nF1, nF2); - aFaceFace.SetFaces(aF1, aF2); - aFaceFace.SetTolFF(aTolFF); - // - IntSurf_ListOfPntOn2S aListOfPnts; - GetEFPnts(nF1, nF2, aListOfPnts); - aNbLP = aListOfPnts.Extent(); - if (aNbLP) { - aFaceFace.SetList(aListOfPnts); + if (myGlue == BOPAlgo_GlueOff) { + BOPAlgo_FaceFace& aFaceFace=aVFaceFace.Append1(); + // + aFaceFace.SetIndices(nF1, nF2); + aFaceFace.SetFaces(aF1, aF2); + aFaceFace.SetTolFF(aTolFF); + // + IntSurf_ListOfPntOn2S aListOfPnts; + GetEFPnts(nF1, nF2, aListOfPnts); + aNbLP = aListOfPnts.Extent(); + if (aNbLP) { + aFaceFace.SetList(aListOfPnts); + } + // + aFaceFace.SetParameters(bApp, bCompC2D1, bCompC2D2, aApproxTol); + aFaceFace.SetFuzzyValue(myFuzzyValue); + aFaceFace.SetProgressIndicator(myProgressIndicator); + } + else { + // for the Glue mode just add all interferences of that type + BOPDS_InterfFF& aFF = aFFs.Append1(); + aFF.SetIndices(nF1, nF2); + aFF.SetTolR3D(Precision::Confusion()); + aFF.SetTolR2D(Precision::PConfusion()); + aFF.SetTolReal(Precision::Confusion()); + aFF.SetTangentFaces(Standard_False); + aFF.Init(0, 0); } - // - aFaceFace.SetParameters(bApp, bCompC2D1, bCompC2D2, aApproxTol); - aFaceFace.SetFuzzyValue(myFuzzyValue); - aFaceFace.SetProgressIndicator(myProgressIndicator); }//for (; myIterator->More(); myIterator->Next()) { // aNbFaceFace=aVFaceFace.Extent(); @@ -358,6 +370,10 @@ void BOPAlgo_PaveFiller::PerformFF() //======================================================================= void BOPAlgo_PaveFiller::MakeBlocks() { + if (myGlue != BOPAlgo_GlueOff) { + return; + } + // Standard_Integer aNbFF; // myErrorStatus=0; diff --git a/src/BOPAlgo/FILES b/src/BOPAlgo/FILES index df1bea264e..b5e68dee23 100644 --- a/src/BOPAlgo/FILES +++ b/src/BOPAlgo/FILES @@ -65,3 +65,4 @@ BOPAlgo_WireSplitter.lxx BOPAlgo_WireSplitter_1.cxx BOPAlgo_CellsBuilder.cxx BOPAlgo_CellsBuilder.hxx +BOPAlgo_GlueEnum.hxx \ No newline at end of file diff --git a/src/BOPTest/BOPTest_APICommands.cxx b/src/BOPTest/BOPTest_APICommands.cxx index 2f37a8145d..a61adc1741 100644 --- a/src/BOPTest/BOPTest_APICommands.cxx +++ b/src/BOPTest/BOPTest_APICommands.cxx @@ -116,6 +116,7 @@ Standard_Integer bapibop(Draw_Interpretor& di, bRunParallel=BOPTest_Objects::RunParallel(); aFuzzyValue=BOPTest_Objects::FuzzyValue(); bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // if (aOp!=BOPAlgo_CUT21) { pBuilder->SetArguments(aLS); @@ -129,6 +130,7 @@ Standard_Integer bapibop(Draw_Interpretor& di, pBuilder->SetRunParallel(bRunParallel); pBuilder->SetFuzzyValue(aFuzzyValue); pBuilder->SetNonDestructive(bNonDestructive); + pBuilder->SetGlue(aGlue); // pBuilder->Build(); iErr=pBuilder->ErrorStatus(); @@ -176,11 +178,13 @@ Standard_Integer bapibuild(Draw_Interpretor& di, bRunParallel=BOPTest_Objects::RunParallel(); aFuzzyValue=BOPTest_Objects::FuzzyValue(); bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // aBuilder.SetArguments(aLS); aBuilder.SetRunParallel(bRunParallel); aBuilder.SetFuzzyValue(aFuzzyValue); aBuilder.SetNonDestructive(bNonDestructive); + aBuilder.SetGlue(aGlue); // aBuilder.Build(); iErr=aBuilder.ErrorStatus(); diff --git a/src/BOPTest/BOPTest_BOPCommands.cxx b/src/BOPTest/BOPTest_BOPCommands.cxx index 631ce39a5c..8b68725f0d 100644 --- a/src/BOPTest/BOPTest_BOPCommands.cxx +++ b/src/BOPTest/BOPTest_BOPCommands.cxx @@ -141,6 +141,7 @@ Standard_Integer bop(Draw_Interpretor& di, aTol=BOPTest_Objects::FuzzyValue(); bRunParallel=BOPTest_Objects::RunParallel(); bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // aLC.Append(aS1); aLC.Append(aS2); @@ -157,6 +158,7 @@ Standard_Integer bop(Draw_Interpretor& di, pPF->SetFuzzyValue(aTol); pPF->SetRunParallel(bRunParallel); pPF->SetNonDestructive(bNonDestructive); + pPF->SetGlue(aGlue); // pPF->Perform(); iErr=pPF->ErrorStatus(); @@ -407,6 +409,7 @@ Standard_Integer bsection(Draw_Interpretor& di, aTol = BOPTest_Objects::FuzzyValue(); bRunParallel = BOPTest_Objects::RunParallel(); bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // for (i = 4; i < n; ++i) { if (!strcmp(a[i], "-n2d")) { @@ -433,6 +436,7 @@ Standard_Integer bsection(Draw_Interpretor& di, aSec.SetFuzzyValue(aTol); aSec.SetRunParallel(bRunParallel); aSec.SetNonDestructive(bNonDestructive); + aSec.SetGlue(aGlue); // aSec.Build(); iErr=aSec.ErrorStatus(); @@ -484,6 +488,7 @@ Standard_Integer bsmt (Draw_Interpretor& di, aTol=BOPTest_Objects::FuzzyValue(); bRunParallel = BOPTest_Objects::RunParallel(); bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // Handle(NCollection_BaseAllocator)aAL= NCollection_BaseAllocator::CommonBaseAllocator(); @@ -495,6 +500,7 @@ Standard_Integer bsmt (Draw_Interpretor& di, aPF.SetFuzzyValue(aTol); aPF.SetRunParallel(bRunParallel); aPF.SetNonDestructive(bNonDestructive); + aPF.SetGlue(aGlue); // aPF.Perform(); iErr=aPF.ErrorStatus(); @@ -739,6 +745,7 @@ Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char** aTol = BOPTest_Objects::FuzzyValue(); bRunParallel = BOPTest_Objects::RunParallel(); bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // bToIntersect = Standard_True; bCompounds = Standard_False; @@ -789,6 +796,7 @@ Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char** aMV.SetRunParallel(bRunParallel); aMV.SetFuzzyValue(aTol); aMV.SetNonDestructive(bNonDestructive); + aMV.SetGlue(aGlue); // aMV.Perform(); if (aMV.ErrorStatus()) { diff --git a/src/BOPTest/BOPTest_CellsCommands.cxx b/src/BOPTest/BOPTest_CellsCommands.cxx index 8956cdb906..3183031621 100644 --- a/src/BOPTest/BOPTest_CellsCommands.cxx +++ b/src/BOPTest/BOPTest_CellsCommands.cxx @@ -80,7 +80,6 @@ Standard_Integer bcbuild(Draw_Interpretor& di, return 1; } // - Standard_Boolean bRunParallel; Standard_Integer iErr; BOPCol_ListIteratorOfListOfShape aIt; // @@ -103,8 +102,16 @@ Standard_Integer bcbuild(Draw_Interpretor& di, aCBuilder.AddArgument(aS); } // - bRunParallel = BOPTest_Objects::RunParallel(); + // set the options to the algorithm + Standard_Boolean bRunParallel = BOPTest_Objects::RunParallel(); + Standard_Real aTol = BOPTest_Objects::FuzzyValue(); + Standard_Boolean bNonDestructive = BOPTest_Objects::NonDestructive(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); + // aCBuilder.SetRunParallel(bRunParallel); + aCBuilder.SetFuzzyValue(aTol); + aCBuilder.SetNonDestructive(bNonDestructive); + aCBuilder.SetGlue(aGlue); // aCBuilder.PerformWithFiller(aPF); iErr = aCBuilder.ErrorStatus(); diff --git a/src/BOPTest/BOPTest_Objects.cxx b/src/BOPTest/BOPTest_Objects.cxx index 338806d6d3..2fad73b694 100644 --- a/src/BOPTest/BOPTest_Objects.cxx +++ b/src/BOPTest/BOPTest_Objects.cxx @@ -52,6 +52,7 @@ class BOPTest_Session { myRunParallel=Standard_False; myNonDestructive = Standard_False; myFuzzyValue = 0.; + myGlue = BOPAlgo_GlueOff; }; // // Clear @@ -123,6 +124,14 @@ class BOPTest_Session { return myNonDestructive; }; // + void SetGlue(const BOPAlgo_GlueEnum theGlue) { + myGlue = theGlue; + }; + // + BOPAlgo_GlueEnum Glue() const { + return myGlue; + }; + // protected: // BOPTest_Session(const BOPTest_Session&); @@ -139,6 +148,7 @@ protected: Standard_Boolean myRunParallel; Standard_Boolean myNonDestructive; Standard_Real myFuzzyValue; + BOPAlgo_GlueEnum myGlue; }; // //======================================================================= @@ -308,6 +318,22 @@ Standard_Boolean BOPTest_Objects::NonDestructive() return GetSession().NonDestructive(); } //======================================================================= +//function : SetGlue +//purpose : +//======================================================================= +void BOPTest_Objects::SetGlue(const BOPAlgo_GlueEnum theGlue) +{ + GetSession().SetGlue(theGlue); +} +//======================================================================= +//function : Glue +//purpose : +//======================================================================= +BOPAlgo_GlueEnum BOPTest_Objects::Glue() +{ + return GetSession().Glue(); +} +//======================================================================= //function : Allocator1 //purpose : //======================================================================= diff --git a/src/BOPTest/BOPTest_Objects.hxx b/src/BOPTest/BOPTest_Objects.hxx index 5283f15582..e1d24ac5c5 100644 --- a/src/BOPTest/BOPTest_Objects.hxx +++ b/src/BOPTest/BOPTest_Objects.hxx @@ -25,6 +25,8 @@ #include #include #include +#include +// class BOPAlgo_PaveFiller; class BOPAlgo_Builder; class BOPAlgo_BOP; @@ -75,7 +77,9 @@ public: Standard_EXPORT static Standard_Boolean NonDestructive(); + Standard_EXPORT static void SetGlue(const BOPAlgo_GlueEnum aGlue); + Standard_EXPORT static BOPAlgo_GlueEnum Glue(); protected: diff --git a/src/BOPTest/BOPTest_OptionCommands.cxx b/src/BOPTest/BOPTest_OptionCommands.cxx index 1c395f6da0..8e38fb7c00 100644 --- a/src/BOPTest/BOPTest_OptionCommands.cxx +++ b/src/BOPTest/BOPTest_OptionCommands.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ static Standard_Integer boptions (Draw_Interpretor&, Standard_Integer, const cha static Standard_Integer brunparallel (Draw_Interpretor&, Standard_Integer, const char**); static Standard_Integer bnondestructive(Draw_Interpretor&, Standard_Integer, const char**); static Standard_Integer bfuzzyvalue(Draw_Interpretor&, Standard_Integer, const char**); +static Standard_Integer bGlue(Draw_Interpretor&, Standard_Integer, const char**); //======================================================================= //function : OptionCommands @@ -41,6 +43,7 @@ void BOPTest::OptionCommands(Draw_Interpretor& theCommands) theCommands.Add("brunparallel", "use brunparallel [0/1]" , __FILE__, brunparallel, g); theCommands.Add("bnondestructive", "use bnondestructive [0/1]", __FILE__, bnondestructive, g); theCommands.Add("bfuzzyvalue", "use bfuzzyvalue value", __FILE__, bfuzzyvalue, g); + theCommands.Add("bglue", "use bglue [0 (off) / 1 (shift) / 2 (full)]", __FILE__, bGlue, g); } //======================================================================= //function : boptions @@ -58,16 +61,21 @@ Standard_Integer boptions(Draw_Interpretor& di, char buf[128]; Standard_Boolean bRunParallel, bNonDestructive; Standard_Real aFuzzyValue; + BOPAlgo_GlueEnum aGlue; // bRunParallel=BOPTest_Objects::RunParallel(); bNonDestructive = BOPTest_Objects::NonDestructive(); aFuzzyValue = BOPTest_Objects::FuzzyValue(); - + aGlue = BOPTest_Objects::Glue(); + // Sprintf(buf, " RunParallel: %d\n", bRunParallel); di << buf; Sprintf(buf, " NonDestructive: %d\n", bNonDestructive); di << buf; - Sprintf(buf, " FuzzyValue : %lf\n", aFuzzyValue); + Sprintf(buf, " FuzzyValue: %lf\n", aFuzzyValue); + di << buf; + Sprintf(buf, " GlueOption: %s\n", ((aGlue == BOPAlgo_GlueOff) ? "Off" : + ((aGlue == BOPAlgo_GlueFull) ? "Full" : "Shift"))); di << buf; // return 0; @@ -151,3 +159,28 @@ Standard_Integer bnondestructive(Draw_Interpretor& di, // return 0; } + +//======================================================================= +//function : bglue +//purpose : +//======================================================================= +Standard_Integer bGlue(Draw_Interpretor& di, + Standard_Integer n, + const char** a) +{ + if (n != 2) { + di << " use bglue [0 (off) / 1 (shift) / 2 (full)]\n"; + return 1; + } + // + Standard_Integer iGlue = Draw::Atoi(a[1]); + if (iGlue < 0 || iGlue > 2) { + di << " Wrong value. Use bglue [0 (off) / 1 (shift) / 2 (full)]\n"; + return 1; + } + // + BOPAlgo_GlueEnum aGlue = BOPAlgo_GlueEnum(iGlue); + BOPTest_Objects::SetGlue(aGlue); + // + return 0; +} diff --git a/src/BOPTest/BOPTest_PartitionCommands.cxx b/src/BOPTest/BOPTest_PartitionCommands.cxx index 5718130952..a86e0c9ba7 100644 --- a/src/BOPTest/BOPTest_PartitionCommands.cxx +++ b/src/BOPTest/BOPTest_PartitionCommands.cxx @@ -83,12 +83,13 @@ Standard_Integer bfillds(Draw_Interpretor& di, bRunParallel=BOPTest_Objects::RunParallel(); bNonDestructive = BOPTest_Objects::NonDestructive(); aTol = BOPTest_Objects::FuzzyValue(); + BOPAlgo_GlueEnum aGlue = BOPTest_Objects::Glue(); // for (i=1; iSetProgressIndicator(myProgressIndicator); myDSFiller->SetFuzzyValue(myFuzzyValue); myDSFiller->SetNonDestructive(myNonDestructive); + myDSFiller->SetGlue(myGlue); // SetAttributes(); // diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx b/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx index da28188c06..f086acbf89 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx @@ -29,7 +29,8 @@ BRepAlgoAPI_BuilderAlgo::BRepAlgoAPI_BuilderAlgo() myDSFiller(NULL), myBuilder(NULL), myFuzzyValue(0.), - myNonDestructive(Standard_False) + myNonDestructive(Standard_False), + myGlue(BOPAlgo_GlueOff) {} //======================================================================= // function: @@ -42,7 +43,8 @@ BRepAlgoAPI_BuilderAlgo::BRepAlgoAPI_BuilderAlgo myEntryType(0), myBuilder(NULL), myFuzzyValue(0.), - myNonDestructive(Standard_False) + myNonDestructive(Standard_False), + myGlue(BOPAlgo_GlueOff) { BOPAlgo_PaveFiller* pPF=(BOPAlgo_PaveFiller*)&aPF; myDSFiller=pPF; @@ -88,6 +90,22 @@ Standard_Boolean BRepAlgoAPI_BuilderAlgo::NonDestructive() const return myNonDestructive; } //======================================================================= +//function : SetGlue +//purpose : +//======================================================================= +void BRepAlgoAPI_BuilderAlgo::SetGlue(const BOPAlgo_GlueEnum theGlue) +{ + myGlue=theGlue; +} +//======================================================================= +//function : Glue +//purpose : +//======================================================================= +BOPAlgo_GlueEnum BRepAlgoAPI_BuilderAlgo::Glue() const +{ + return myGlue; +} +//======================================================================= //function : Clear //purpose : //======================================================================= @@ -144,6 +162,7 @@ void BRepAlgoAPI_BuilderAlgo::Build() myDSFiller->SetProgressIndicator(myProgressIndicator); myDSFiller->SetFuzzyValue(myFuzzyValue); myDSFiller->SetNonDestructive(myNonDestructive); + myDSFiller->SetGlue(myGlue); // myDSFiller->Perform(); iErr=myDSFiller->ErrorStatus(); diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.hxx b/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.hxx index 9ed9b27f90..d7e5640c8a 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.hxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.hxx @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,12 @@ Standard_EXPORT virtual ~BRepAlgoAPI_BuilderAlgo(); //! a copy of a sub-shape is created in the result if it is needed to be updated. Standard_EXPORT Standard_Boolean NonDestructive() const; + //! Sets the glue option for the algorithm + Standard_EXPORT void SetGlue(const BOPAlgo_GlueEnum theGlue); + + //! Returns the glue option of the algorithm + Standard_EXPORT BOPAlgo_GlueEnum Glue() const; + //! Sets the arguments Standard_EXPORT void SetArguments (const TopTools_ListOfShape& theLS); @@ -113,6 +120,7 @@ protected: Standard_Real myFuzzyValue; Standard_Boolean myNonDestructive; TopTools_ListOfShape myArguments; + BOPAlgo_GlueEnum myGlue; private: diff --git a/tests/bugs/modalg_6/bug27878_1 b/tests/bugs/modalg_6/bug27878_1 new file mode 100644 index 0000000000..e0e0525747 --- /dev/null +++ b/tests/bugs/modalg_6/bug27878_1 @@ -0,0 +1,24 @@ +puts "========" +puts "OCC27878" +puts "========" +puts "" +################################################# +# Development of the Gluing operations based on the new Boolean component +################################################# + +# planar boxes + +restore [locate_data_file bug27878_shapes1.brep] c + +# fusing the solids using the glue option +bglue 2 +bclearobjects +bcleartools +baddobjects {*}[explode c so] +bfillds -t +bbuild result + +checknbshapes result -face 1176 -solid 343 +checkprops result -s 2058 -v 343 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27878_2 b/tests/bugs/modalg_6/bug27878_2 new file mode 100644 index 0000000000..57b1dbdee9 --- /dev/null +++ b/tests/bugs/modalg_6/bug27878_2 @@ -0,0 +1,24 @@ +puts "========" +puts "OCC27878" +puts "========" +puts "" +################################################# +# Development of the Gluing operations based on the new Boolean component +################################################# + +# bspline boxes + +restore [locate_data_file bug27878_shapes2.brep] c + +# fusing the solids using the glue option +bglue 2 +bclearobjects +bcleartools +baddobjects {*}[explode c so] +bfillds -t +bbuild result + +checknbshapes result -face 240 -solid 64 +checkprops result -s 384 -v 64 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27878_3 b/tests/bugs/modalg_6/bug27878_3 new file mode 100644 index 0000000000..c351cce0c1 --- /dev/null +++ b/tests/bugs/modalg_6/bug27878_3 @@ -0,0 +1,24 @@ +puts "========" +puts "OCC27878" +puts "========" +puts "" +################################################# +# Development of the Gluing operations based on the new Boolean component +################################################# + +# planar boxes shifted x y + +restore [locate_data_file bug27878_shapes3.brep] c + +# fusing the solids using the glue option +bglue 1 +bclearobjects +bcleartools +baddobjects {*}[explode c so] +bfillds -t +bbuild result + +checknbshapes result -face 2052 -solid 343 +checkprops result -s 2058 -v 343 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27878_4 b/tests/bugs/modalg_6/bug27878_4 new file mode 100644 index 0000000000..e547068c0d --- /dev/null +++ b/tests/bugs/modalg_6/bug27878_4 @@ -0,0 +1,24 @@ +puts "========" +puts "OCC27878" +puts "========" +puts "" +################################################# +# Development of the Gluing operations based on the new Boolean component +################################################# + +# bspline boxes shifted x y + +restore [locate_data_file bug27878_shapes4.brep] c + +# fusing the solids using the glue option +bglue 1 +bclearobjects +bcleartools +baddobjects {*}[explode c so] +bfillds -t +bbuild result + +checknbshapes result -face 381 -solid 64 +checkprops result -s 384 -v 64 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27878_5 b/tests/bugs/modalg_6/bug27878_5 new file mode 100644 index 0000000000..1031bbbab9 --- /dev/null +++ b/tests/bugs/modalg_6/bug27878_5 @@ -0,0 +1,26 @@ +puts "========" +puts "OCC27878" +puts "========" +puts "" +################################################# +# Development of the Gluing operations based on the new Boolean component +################################################# + +restore [locate_data_file bug28165_shapes3.brep] c + +# fuse the shapes +bglue 1 +bclearobjects +bcleartools +baddobjects {*}[explode c so] +bfillds -t + +# remove all internal faces to make only one solid +bcbuild rx +bcaddall result -m 1 -u + +checkshape result +checknbshapes result -edge 1400 -face 506 -solid 1 +checkprops result -v 4.69342e+007 -s 1.38778e+006 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug27878_6 b/tests/bugs/modalg_6/bug27878_6 new file mode 100644 index 0000000000..a5c364c616 --- /dev/null +++ b/tests/bugs/modalg_6/bug27878_6 @@ -0,0 +1,46 @@ +puts "========" +puts "OCC27878" +puts "========" +puts "" +################################################# +# Development of the Gluing operations based on the new Boolean component +################################################# + +compound sh +for {set i 0} {$i < 4} {incr i} { + for {set j 0} {$j < 4} {incr j} { + box b 1 1 1; + ttranslate b $i $j 0; + add b sh + } +} + +nurbsconvert b1 sh + +#fuse boxes using glue full option +bglue 2 + +bclearobjects +bcleartools +baddobjects {*}[explode b1 so] +bfillds -t +bcbuild rx +bcaddall res1 -m 1 -u + +copy res1 b2 +ttranslate b2 0.5 0.5 1 + +# fuse two solids using glue shift +bglue 1 + +chrono t reset; chrono t start +bop res1 b2 +chrono t stop; chrono t show + +bopfuse result + +checkshape result +checknbshapes result -face 78 -solid 1 +checkprops result -s 71.5 -v 32 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file