From 8d2ebfcc11d73c6f6b4781ab5b5ae1ad4b5c32b9 Mon Sep 17 00:00:00 2001 From: emv Date: Wed, 1 Nov 2017 11:30:30 +0300 Subject: [PATCH] Implementation of the Oriented Bounding Boxes using PCA-based algorithm to use in Boolean operations for filtering of the intersections. OBB is implemented in IntTools_OBB class, and is represented as center, axes and half-size dimensions. The method IntTools_OBB::IsOut(theOther) is based on the Separated Axes theorem for Oriented Bounding Boxes. According to this theorem it is necessary to consider 15 separating axes. By default the OBB are not used. To enable the OBB usage in Boolean Operations it is necessary to call the method BOPAlgo_PaveFiller::SetUseOBB(const Standard_Boolean theFlag) with TRUE value. To enable OBB usage in DRAW it is necessary to use the command: buseobb 1 --- src/BOPAlgo/BOPAlgo_BOP.cxx | 1 + src/BOPAlgo/BOPAlgo_Builder.cxx | 2 + src/BOPAlgo/BOPAlgo_CheckerSI.cxx | 10 +- src/BOPAlgo/BOPAlgo_MakerVolume.cxx | 1 + src/BOPAlgo/BOPAlgo_Options.cxx | 6 +- src/BOPAlgo/BOPAlgo_Options.hxx | 18 ++ src/BOPAlgo/BOPAlgo_PaveFiller.cxx | 10 +- src/BOPAlgo/BOPAlgo_Splitter.cxx | 1 + src/BOPDS/BOPDS_Iterator.cxx | 31 ++- src/BOPDS/BOPDS_Iterator.hxx | 8 +- src/BOPDS/BOPDS_IteratorSI.cxx | 14 +- src/BOPDS/BOPDS_IteratorSI.hxx | 3 +- src/BOPTest/BOPTest_APICommands.cxx | 3 + src/BOPTest/BOPTest_BOPCommands.cxx | 4 + src/BOPTest/BOPTest_CellsCommands.cxx | 1 + src/BOPTest/BOPTest_DebugCommands.cxx | 5 +- src/BOPTest/BOPTest_Objects.cxx | 25 +++ src/BOPTest/BOPTest_Objects.hxx | 4 + src/BOPTest/BOPTest_OptionCommands.cxx | 24 +++ src/BOPTest/BOPTest_PartitionCommands.cxx | 1 + src/BRepAlgoAPI/BRepAlgoAPI_Algo.hxx | 1 + .../BRepAlgoAPI_BooleanOperation.cxx | 1 + src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx | 1 + src/BRepAlgoAPI/BRepAlgoAPI_Splitter.cxx | 1 + src/IntTools/FILES | 2 + src/IntTools/IntTools_Context.cxx | 42 ++++ src/IntTools/IntTools_Context.hxx | 7 +- src/IntTools/IntTools_OBB.cxx | 125 +++++++++++ src/IntTools/IntTools_OBB.hxx | 199 ++++++++++++++++++ src/IntTools/IntTools_Tools.cxx | 122 +++++++++++ src/IntTools/IntTools_Tools.hxx | 12 +- 31 files changed, 660 insertions(+), 25 deletions(-) create mode 100644 src/IntTools/IntTools_OBB.cxx create mode 100644 src/IntTools/IntTools_OBB.hxx diff --git a/src/BOPAlgo/BOPAlgo_BOP.cxx b/src/BOPAlgo/BOPAlgo_BOP.cxx index 7004b3ac3b..82bb2e103c 100644 --- a/src/BOPAlgo/BOPAlgo_BOP.cxx +++ b/src/BOPAlgo/BOPAlgo_BOP.cxx @@ -411,6 +411,7 @@ void BOPAlgo_BOP::Perform() pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); pPF->SetGlue(myGlue); + pPF->SetUseOBB(myUseOBB); // pPF->Perform(); // diff --git a/src/BOPAlgo/BOPAlgo_Builder.cxx b/src/BOPAlgo/BOPAlgo_Builder.cxx index 9b2302f554..20f74f4362 100644 --- a/src/BOPAlgo/BOPAlgo_Builder.cxx +++ b/src/BOPAlgo/BOPAlgo_Builder.cxx @@ -286,6 +286,7 @@ void BOPAlgo_Builder::Perform() pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); pPF->SetGlue(myGlue); + pPF->SetUseOBB(myUseOBB); // pPF->Perform(); // @@ -303,6 +304,7 @@ void BOPAlgo_Builder::PerformWithFiller(const BOPAlgo_PaveFiller& theFiller) myNonDestructive = theFiller.NonDestructive(); myFuzzyValue = theFiller.FuzzyValue(); myGlue = theFiller.Glue(); + myUseOBB = theFiller.UseOBB(); PerformInternal(theFiller); } //======================================================================= diff --git a/src/BOPAlgo/BOPAlgo_CheckerSI.cxx b/src/BOPAlgo/BOPAlgo_CheckerSI.cxx index 35dfe50e7b..f1f448503e 100644 --- a/src/BOPAlgo/BOPAlgo_CheckerSI.cxx +++ b/src/BOPAlgo/BOPAlgo_CheckerSI.cxx @@ -159,16 +159,16 @@ void BOPAlgo_CheckerSI::Init() myDS->SetArguments(myArguments); myDS->Init(myFuzzyValue); // - // 2.myIterator + // 2 myContext + myContext=new IntTools_Context; + // + // 3.myIterator BOPDS_PIteratorSI theIterSI=new BOPDS_IteratorSI(myAllocator); theIterSI->SetDS(myDS); - theIterSI->Prepare(); + theIterSI->Prepare(myContext, myUseOBB); theIterSI->UpdateByLevelOfCheck(myLevelOfCheck); // myIterator=theIterSI; - // - // 3 myContext - myContext=new IntTools_Context; } //======================================================================= //function : Perform diff --git a/src/BOPAlgo/BOPAlgo_MakerVolume.cxx b/src/BOPAlgo/BOPAlgo_MakerVolume.cxx index 695118a397..31777c2a72 100644 --- a/src/BOPAlgo/BOPAlgo_MakerVolume.cxx +++ b/src/BOPAlgo/BOPAlgo_MakerVolume.cxx @@ -94,6 +94,7 @@ void BOPAlgo_MakerVolume::Perform() pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); pPF->SetGlue(myGlue); + pPF->SetUseOBB(myUseOBB); pPF->Perform(); // myEntryPoint = 1; diff --git a/src/BOPAlgo/BOPAlgo_Options.cxx b/src/BOPAlgo/BOPAlgo_Options.cxx index ac5445b4d0..a8864186d2 100644 --- a/src/BOPAlgo/BOPAlgo_Options.cxx +++ b/src/BOPAlgo/BOPAlgo_Options.cxx @@ -51,7 +51,8 @@ BOPAlgo_Options::BOPAlgo_Options() myReport(new Message_Report), myRunParallel(myGlobalRunParallel), myFuzzyValue(Precision::Confusion()), - myCheckInverted(Standard_True) + myCheckInverted(Standard_True), + myUseOBB(Standard_False) { BOPAlgo_LoadMessages(); } @@ -67,7 +68,8 @@ BOPAlgo_Options::BOPAlgo_Options myReport(new Message_Report), myRunParallel(myGlobalRunParallel), myFuzzyValue(Precision::Confusion()), - myCheckInverted(Standard_True) + myCheckInverted(Standard_True), + myUseOBB(Standard_False) { BOPAlgo_LoadMessages(); } diff --git a/src/BOPAlgo/BOPAlgo_Options.hxx b/src/BOPAlgo/BOPAlgo_Options.hxx index e10cf0e1ec..4b61ff602f 100644 --- a/src/BOPAlgo/BOPAlgo_Options.hxx +++ b/src/BOPAlgo/BOPAlgo_Options.hxx @@ -36,6 +36,8 @@ class Message_ProgressIndicator; //! for inverted status (holes in the space). The default value is TRUE, //! i.e. the check is performed. Setting this flag to FALSE for inverted solids, //! most likely will lead to incorrect results. +//! - *Using the Oriented Bounding Boxes* - Allows using the Oriented Bounding Boxes of the shapes +//! for filtering the intersections. //! class BOPAlgo_Options { @@ -176,6 +178,21 @@ public: return myCheckInverted; } +public: + //!@name Usage of Oriented Bounding boxes + + //! Enables/Disables the usage of OBB + void SetUseOBB(const Standard_Boolean theUseOBB) + { + myUseOBB = theUseOBB; + } + + //! Returns the flag defining usage of OBB + Standard_Boolean UseOBB() const + { + return myUseOBB; + } + protected: //! Breaks the execution if the break signal @@ -190,6 +207,7 @@ protected: Standard_Real myFuzzyValue; Handle(Message_ProgressIndicator) myProgressIndicator; Standard_Boolean myCheckInverted; + Standard_Boolean myUseOBB; }; diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx index 5867221f5e..00e89a19bf 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx @@ -211,14 +211,14 @@ void BOPAlgo_PaveFiller::Init() myDS->SetArguments(myArguments); myDS->Init(myFuzzyValue); // - // 2.myIterator + // 2 myContext + myContext=new IntTools_Context; + // + // 3.myIterator myIterator=new BOPDS_Iterator(myAllocator); myIterator->SetRunParallel(myRunParallel); myIterator->SetDS(myDS); - myIterator->Prepare(); - // - // 3 myContext - myContext=new IntTools_Context; + myIterator->Prepare(myContext, myUseOBB); // // 4 NonDestructive flag SetNonDestructive(); diff --git a/src/BOPAlgo/BOPAlgo_Splitter.cxx b/src/BOPAlgo/BOPAlgo_Splitter.cxx index 0d073b08c8..8c4a4720b1 100644 --- a/src/BOPAlgo/BOPAlgo_Splitter.cxx +++ b/src/BOPAlgo/BOPAlgo_Splitter.cxx @@ -131,6 +131,7 @@ void BOPAlgo_Splitter::Perform() pPF->SetFuzzyValue(myFuzzyValue); pPF->SetNonDestructive(myNonDestructive); pPF->SetGlue(myGlue); + pPF->SetUseOBB(myUseOBB); // pPF->Perform(); // diff --git a/src/BOPDS/BOPDS_Iterator.cxx b/src/BOPDS/BOPDS_Iterator.cxx index d3e80582ad..b8c4fc78ef 100644 --- a/src/BOPDS/BOPDS_Iterator.cxx +++ b/src/BOPDS/BOPDS_Iterator.cxx @@ -29,6 +29,12 @@ #include #include #include +#include +#include + +#ifdef DEBUG_OBB +#include +#endif ///////////////////////////////////////////////////////////////////////// //======================================================================= @@ -240,7 +246,8 @@ void BOPDS_Iterator::Value(Standard_Integer& theI1, // function: Prepare // purpose: //======================================================================= -void BOPDS_Iterator::Prepare() +void BOPDS_Iterator::Prepare(Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB) { Standard_Integer i, aNbInterfTypes; // @@ -253,14 +260,15 @@ void BOPDS_Iterator::Prepare() if (myDS==NULL){ return; } - Intersect(); + Intersect(theCtx, theCheckOBB); } // //======================================================================= // function: Intersect // purpose: //======================================================================= -void BOPDS_Iterator::Intersect() +void BOPDS_Iterator::Intersect(Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB) { Standard_Integer i, j, iX, i1, i2, iR, aNb, aNbR; Standard_Integer iTi, iTj; @@ -304,7 +312,7 @@ void BOPDS_Iterator::Intersect() i1 = aR.First(); i2 = aR.Last(); for (i = i1; i <= i2; ++i) { - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); + BOPDS_ShapeInfo& aSI = myDS->ChangeShapeInfo(i); // if (!aSI.IsInterfering() || (aSI.ShapeType() == TopAbs_SOLID)) { continue; @@ -327,7 +335,7 @@ void BOPDS_Iterator::Intersect() continue;// same range } // - const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j); + BOPDS_ShapeInfo& aSJ = myDS->ChangeShapeInfo(j); aTj = aSJ.ShapeType(); iTj = BOPDS_Tools::TypeToInteger(aTj); // @@ -339,6 +347,19 @@ void BOPDS_Iterator::Intersect() // BOPDS_Pair aPair(i, j); if (aMPFence.Add(aPair)) { + if (theCheckOBB) + { + IntTools_OBB& anOBBi = theCtx->OBB(aSI.Shape(), aSI.Box().GetGap()); + IntTools_OBB& anOBBj = theCtx->OBB(aSJ.Shape(), aSJ.Box().GetGap()); + +#ifdef DEBUG_OBB + TopoDS_Shape aBox1 = IntTools_Tools::GetOBBShapeBox(anOBBi); + TopoDS_Shape aBox2 = IntTools_Tools::GetOBBShapeBox(anOBBj); +#endif + if (anOBBi.IsOut(anOBBj)) + continue; + } + iX = BOPDS_Tools::TypeToInteger(aTi, aTj); myLists(iX).Append(aPair); }// if (aMPFence.Add(aPair)) { diff --git a/src/BOPDS/BOPDS_Iterator.hxx b/src/BOPDS/BOPDS_Iterator.hxx index 9e3313092b..848ed56608 100644 --- a/src/BOPDS/BOPDS_Iterator.hxx +++ b/src/BOPDS/BOPDS_Iterator.hxx @@ -30,7 +30,7 @@ #include #include class BOPDS_DS; - +class IntTools_Context; //! The class BOPDS_Iterator is @@ -81,7 +81,8 @@ public: //! Perform the intersection algorithm and prepare //! the results to be used - Standard_EXPORT virtual void Prepare(); + Standard_EXPORT virtual void Prepare(Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB = Standard_False); //! Returns the number of intersections founded Standard_EXPORT Standard_Integer ExpectedLength() const; @@ -99,7 +100,8 @@ public: protected: - Standard_EXPORT virtual void Intersect(); + Standard_EXPORT virtual void Intersect(Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB = Standard_False); BOPCol_BaseAllocator myAllocator; Standard_Integer myLength; diff --git a/src/BOPDS/BOPDS_IteratorSI.cxx b/src/BOPDS/BOPDS_IteratorSI.cxx index 2feaa9b761..c35ed5357d 100644 --- a/src/BOPDS/BOPDS_IteratorSI.cxx +++ b/src/BOPDS/BOPDS_IteratorSI.cxx @@ -33,6 +33,8 @@ #include #include #include +#include +#include // //======================================================================= @@ -78,7 +80,8 @@ void BOPDS_IteratorSI::UpdateByLevelOfCheck(const Standard_Integer theLevel) // function: Intersect // purpose: //======================================================================= -void BOPDS_IteratorSI::Intersect() +void BOPDS_IteratorSI::Intersect(Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB) { Standard_Integer i, j, iX, aNbS; Standard_Integer iTi, iTj; @@ -138,6 +141,15 @@ void BOPDS_IteratorSI::Intersect() // BOPDS_Pair aPair(i, j); if (aMPFence.Add(aPair)) { + if (theCheckOBB) + { + IntTools_OBB& anOBBi = theCtx->OBB(aSI.Shape(), aSI.Box().GetGap()); + IntTools_OBB& anOBBj = theCtx->OBB(aSJ.Shape(), aSJ.Box().GetGap()); + + if (anOBBi.IsOut(anOBBj)) + continue; + } + iX = BOPDS_Tools::TypeToInteger(aTi, aTj); myLists(iX).Append(aPair); }// if (aMPKXB.Add(aPKXB)) { diff --git a/src/BOPDS/BOPDS_IteratorSI.hxx b/src/BOPDS/BOPDS_IteratorSI.hxx index a0d9b9ab45..3783e43c4a 100644 --- a/src/BOPDS/BOPDS_IteratorSI.hxx +++ b/src/BOPDS/BOPDS_IteratorSI.hxx @@ -68,7 +68,8 @@ Standard_EXPORT virtual ~BOPDS_IteratorSI(); protected: - Standard_EXPORT virtual void Intersect() Standard_OVERRIDE; + Standard_EXPORT virtual void Intersect(Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB = Standard_False) Standard_OVERRIDE; diff --git a/src/BOPTest/BOPTest_APICommands.cxx b/src/BOPTest/BOPTest_APICommands.cxx index 4096800bdf..b6ce3f102b 100644 --- a/src/BOPTest/BOPTest_APICommands.cxx +++ b/src/BOPTest/BOPTest_APICommands.cxx @@ -134,6 +134,7 @@ Standard_Integer bapibop(Draw_Interpretor& di, pBuilder->SetNonDestructive(bNonDestructive); pBuilder->SetGlue(aGlue); pBuilder->SetCheckInverted(BOPTest_Objects::CheckInverted()); + pBuilder->SetUseOBB(BOPTest_Objects::UseOBB()); // pBuilder->Build(); // @@ -195,6 +196,7 @@ Standard_Integer bapibuild(Draw_Interpretor& di, aBuilder.SetNonDestructive(bNonDestructive); aBuilder.SetGlue(aGlue); aBuilder.SetCheckInverted(BOPTest_Objects::CheckInverted()); + aBuilder.SetUseOBB(BOPTest_Objects::UseOBB()); // aBuilder.Build(); // @@ -260,6 +262,7 @@ Standard_Integer bapisplit(Draw_Interpretor& di, aSplitter.SetNonDestructive(BOPTest_Objects::NonDestructive()); aSplitter.SetGlue(BOPTest_Objects::Glue()); aSplitter.SetCheckInverted(BOPTest_Objects::CheckInverted()); + aSplitter.SetUseOBB(BOPTest_Objects::UseOBB()); // // performing operation aSplitter.Build(); diff --git a/src/BOPTest/BOPTest_BOPCommands.cxx b/src/BOPTest/BOPTest_BOPCommands.cxx index 427f052cab..bb1e09c186 100644 --- a/src/BOPTest/BOPTest_BOPCommands.cxx +++ b/src/BOPTest/BOPTest_BOPCommands.cxx @@ -158,6 +158,7 @@ Standard_Integer bop(Draw_Interpretor& di, pPF->SetRunParallel(bRunParallel); pPF->SetNonDestructive(bNonDestructive); pPF->SetGlue(aGlue); + pPF->SetUseOBB(BOPTest_Objects::UseOBB()); // pPF->Perform(); BOPTest::ReportAlerts(*pPF); @@ -427,6 +428,7 @@ Standard_Integer bsection(Draw_Interpretor& di, aSec.SetRunParallel(bRunParallel); aSec.SetNonDestructive(bNonDestructive); aSec.SetGlue(aGlue); + aSec.SetUseOBB(BOPTest_Objects::UseOBB()); // aSec.Build(); // @@ -496,6 +498,7 @@ Standard_Integer bsmt (Draw_Interpretor& di, aPF.SetRunParallel(bRunParallel); aPF.SetNonDestructive(bNonDestructive); aPF.SetGlue(aGlue); + aPF.SetUseOBB(BOPTest_Objects::UseOBB()); // aPF.Perform(); BOPTest::ReportAlerts(aPF); @@ -818,6 +821,7 @@ Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char** aMV.SetNonDestructive(bNonDestructive); aMV.SetAvoidInternalShapes(bAvoidInternal); aMV.SetGlue(aGlue); + aMV.SetUseOBB(BOPTest_Objects::UseOBB()); // aMV.Perform(); BOPTest::ReportAlerts(aMV); diff --git a/src/BOPTest/BOPTest_CellsCommands.cxx b/src/BOPTest/BOPTest_CellsCommands.cxx index 0373053146..87b09cc281 100644 --- a/src/BOPTest/BOPTest_CellsCommands.cxx +++ b/src/BOPTest/BOPTest_CellsCommands.cxx @@ -112,6 +112,7 @@ Standard_Integer bcbuild(Draw_Interpretor& di, aCBuilder.SetNonDestructive(bNonDestructive); aCBuilder.SetGlue(aGlue); aCBuilder.SetCheckInverted(BOPTest_Objects::CheckInverted()); + aCBuilder.SetUseOBB(BOPTest_Objects::UseOBB()); // aCBuilder.PerformWithFiller(aPF); BOPTest::ReportAlerts(aCBuilder); diff --git a/src/BOPTest/BOPTest_DebugCommands.cxx b/src/BOPTest/BOPTest_DebugCommands.cxx index f5b5279e40..0b42c4b196 100644 --- a/src/BOPTest/BOPTest_DebugCommands.cxx +++ b/src/BOPTest/BOPTest_DebugCommands.cxx @@ -40,6 +40,7 @@ #include #include +#include static void GetTypeByName(const char* theName, @@ -239,9 +240,11 @@ Standard_Integer bopiterator (Draw_Interpretor& di, char buf[64], aST1[10], aST2[10]; BOPDS_Iterator aIt; // + Handle(IntTools_Context) aCtx = new IntTools_Context(); + BOPDS_DS& aDS = *pDS; aIt.SetDS(&aDS); - aIt.Prepare(); + aIt.Prepare(aCtx, BOPTest_Objects::UseOBB()); // if (n == 1) { // type has not been defined. show all pairs diff --git a/src/BOPTest/BOPTest_Objects.cxx b/src/BOPTest/BOPTest_Objects.cxx index 61c3416fa2..401b6d735a 100644 --- a/src/BOPTest/BOPTest_Objects.cxx +++ b/src/BOPTest/BOPTest_Objects.cxx @@ -56,6 +56,7 @@ class BOPTest_Session { myGlue = BOPAlgo_GlueOff; myDrawWarnShapes = Standard_False; myCheckInverted = Standard_True; + myUseOBB = Standard_False; }; // // Clear @@ -151,6 +152,13 @@ class BOPTest_Session { return myCheckInverted; }; // + void SetUseOBB(const Standard_Boolean bUse) { + myUseOBB = bUse; + }; + // + Standard_Boolean UseOBB() const { + return myUseOBB; + }; protected: // BOPTest_Session(const BOPTest_Session&); @@ -170,6 +178,7 @@ protected: BOPAlgo_GlueEnum myGlue; Standard_Boolean myDrawWarnShapes; Standard_Boolean myCheckInverted; + Standard_Boolean myUseOBB; }; // //======================================================================= @@ -396,6 +405,22 @@ Standard_Boolean BOPTest_Objects::CheckInverted() return GetSession().CheckInverted(); } //======================================================================= +//function : SetUseOBB +//purpose : +//======================================================================= +void BOPTest_Objects::SetUseOBB(const Standard_Boolean bUseOBB) +{ + GetSession().SetUseOBB(bUseOBB); +} +//======================================================================= +//function : UseOBB +//purpose : +//======================================================================= +Standard_Boolean BOPTest_Objects::UseOBB() +{ + return GetSession().UseOBB(); +} +//======================================================================= //function : Allocator1 //purpose : //======================================================================= diff --git a/src/BOPTest/BOPTest_Objects.hxx b/src/BOPTest/BOPTest_Objects.hxx index 02911bc0d0..221f0e66d8 100644 --- a/src/BOPTest/BOPTest_Objects.hxx +++ b/src/BOPTest/BOPTest_Objects.hxx @@ -91,6 +91,10 @@ public: Standard_EXPORT static Standard_Boolean CheckInverted(); + Standard_EXPORT static void SetUseOBB(const Standard_Boolean bUseOBB); + + Standard_EXPORT static Standard_Boolean UseOBB(); + protected: private: diff --git a/src/BOPTest/BOPTest_OptionCommands.cxx b/src/BOPTest/BOPTest_OptionCommands.cxx index b90a40f5ec..be4b06330c 100644 --- a/src/BOPTest/BOPTest_OptionCommands.cxx +++ b/src/BOPTest/BOPTest_OptionCommands.cxx @@ -28,6 +28,7 @@ static Standard_Integer bfuzzyvalue(Draw_Interpretor&, Standard_Integer, const c static Standard_Integer bGlue(Draw_Interpretor&, Standard_Integer, const char**); static Standard_Integer bdrawwarnshapes(Draw_Interpretor&, Standard_Integer, const char**); static Standard_Integer bcheckinverted(Draw_Interpretor&, Standard_Integer, const char**); +static Standard_Integer buseobb(Draw_Interpretor&, Standard_Integer, const char**); //======================================================================= //function : OptionCommands @@ -51,6 +52,8 @@ void BOPTest::OptionCommands(Draw_Interpretor& theCommands) __FILE__, bdrawwarnshapes, g); theCommands.Add("bcheckinverted", "Defines whether to check the input solids on inverted status or not\n" "Usage: bcheckinverted [0 (off) / 1 (on)]", __FILE__, bcheckinverted, g); + theCommands.Add("buseobb", "Enables/disables the usage of OBB\n" + "Usage: buseobb [0 (off) / 1 (on)]", __FILE__, buseobb, g); } //======================================================================= //function : boptions @@ -76,6 +79,7 @@ Standard_Integer boptions(Draw_Interpretor& di, aGlue = BOPTest_Objects::Glue(); Standard_Boolean bDrawWarnShapes = BOPTest_Objects::DrawWarnShapes(); Standard_Boolean bCheckInverted = BOPTest_Objects::CheckInverted(); + Standard_Boolean bUseOBB = BOPTest_Objects::UseOBB(); // Sprintf(buf, " RunParallel: %d\n", bRunParallel); di << buf; @@ -90,6 +94,8 @@ Standard_Integer boptions(Draw_Interpretor& di, di << buf; Sprintf(buf, " Check for inverted solids: %s\n", bCheckInverted ? "Yes" : "No"); di << buf; + Sprintf(buf, " Use OBB:%s\n", bUseOBB ? "Yes" : "No"); + di << buf; // return 0; } @@ -233,3 +239,21 @@ Standard_Integer bcheckinverted(Draw_Interpretor& di, BOPTest_Objects::SetCheckInverted(iCheck != 0); return 0; } + +//======================================================================= +//function : buseobb +//purpose : +//======================================================================= +Standard_Integer buseobb(Draw_Interpretor& di, + Standard_Integer n, + const char** a) +{ + if (n != 2) { + di.PrintHelp(a[0]); + return 1; + } + // + Standard_Integer iUse = Draw::Atoi(a[1]); + BOPTest_Objects::SetUseOBB(iUse != 0); + return 0; +} diff --git a/src/BOPTest/BOPTest_PartitionCommands.cxx b/src/BOPTest/BOPTest_PartitionCommands.cxx index 9cc1cea800..148f3d1266 100644 --- a/src/BOPTest/BOPTest_PartitionCommands.cxx +++ b/src/BOPTest/BOPTest_PartitionCommands.cxx @@ -115,6 +115,7 @@ Standard_Integer bfillds(Draw_Interpretor& di, aPF.SetNonDestructive(bNonDestructive); aPF.SetFuzzyValue(aTol); aPF.SetGlue(aGlue); + aPF.SetUseOBB(BOPTest_Objects::UseOBB()); // OSD_Timer aTimer; aTimer.Start(); diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_Algo.hxx b/src/BRepAlgoAPI/BRepAlgoAPI_Algo.hxx index 1850e0e7dc..ef65c4939b 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_Algo.hxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_Algo.hxx @@ -56,6 +56,7 @@ public: using BOPAlgo_Options::GetReport; using BOPAlgo_Options::SetProgressIndicator; using BOPAlgo_Options::SetCheckInverted; + using BOPAlgo_Options::SetUseOBB; protected: diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_BooleanOperation.cxx b/src/BRepAlgoAPI/BRepAlgoAPI_BooleanOperation.cxx index dbddf3dd93..e3b9205824 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_BooleanOperation.cxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_BooleanOperation.cxx @@ -311,6 +311,7 @@ void BRepAlgoAPI_BooleanOperation::Build() myDSFiller->SetFuzzyValue(myFuzzyValue); myDSFiller->SetNonDestructive(myNonDestructive); myDSFiller->SetGlue(myGlue); + myDSFiller->SetUseOBB(myUseOBB); // SetAttributes(); // diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx b/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx index f0c565f770..e746b5bac1 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx @@ -143,6 +143,7 @@ void BRepAlgoAPI_BuilderAlgo::Build() myDSFiller->SetFuzzyValue(myFuzzyValue); myDSFiller->SetNonDestructive(myNonDestructive); myDSFiller->SetGlue(myGlue); + myDSFiller->SetUseOBB(myUseOBB); // myDSFiller->Perform(); // diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_Splitter.cxx b/src/BRepAlgoAPI/BRepAlgoAPI_Splitter.cxx index b28fb2f373..97b75ff7d8 100644 --- a/src/BRepAlgoAPI/BRepAlgoAPI_Splitter.cxx +++ b/src/BRepAlgoAPI/BRepAlgoAPI_Splitter.cxx @@ -98,6 +98,7 @@ void BRepAlgoAPI_Splitter::Build() myDSFiller->SetFuzzyValue(myFuzzyValue); myDSFiller->SetNonDestructive(myNonDestructive); myDSFiller->SetGlue(myGlue); + myDSFiller->SetUseOBB(myUseOBB); // myDSFiller->Perform(); // diff --git a/src/IntTools/FILES b/src/IntTools/FILES index e5290ffb49..6649e5f24b 100644 --- a/src/IntTools/FILES +++ b/src/IntTools/FILES @@ -55,6 +55,8 @@ IntTools_MapOfSurfaceSample.hxx IntTools_MarkedRangeSet.cxx IntTools_MarkedRangeSet.hxx IntTools_MarkedRangeSet.lxx +IntTools_OBB.cxx +IntTools_OBB.hxx IntTools_PntOn2Faces.cxx IntTools_PntOn2Faces.hxx IntTools_PntOnFace.cxx diff --git a/src/IntTools/IntTools_Context.cxx b/src/IntTools/IntTools_Context.cxx index 903a0e38f9..a9700fc721 100644 --- a/src/IntTools/IntTools_Context.cxx +++ b/src/IntTools/IntTools_Context.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ IntTools_Context::IntTools_Context() myProjSDataMap(100, myAllocator), myBndBoxDataMap(100, myAllocator), mySurfAdaptorMap(100, myAllocator), + myOBBMap(100, myAllocator), myCreateFlag(0), myPOnSTolerance(1.e-12) { @@ -86,6 +88,7 @@ IntTools_Context::IntTools_Context myProjSDataMap(100, myAllocator), myBndBoxDataMap(100, myAllocator), mySurfAdaptorMap(100, myAllocator), + myOBBMap(100, myAllocator), myCreateFlag(1), myPOnSTolerance(1.e-12) { @@ -183,6 +186,16 @@ IntTools_Context::~IntTools_Context() myAllocator->Free(anAdr); } mySurfAdaptorMap.Clear(); + // + IntTools_OBB* pOBB; + aIt.Initialize(myOBBMap); + for (; aIt.More(); aIt.Next()) { + anAdr=aIt.Value(); + pOBB=(IntTools_OBB*)anAdr; + (*pOBB).~IntTools_OBB(); + myAllocator->Free(anAdr); + } + myOBBMap.Clear(); } //======================================================================= //function : BndBox @@ -472,6 +485,35 @@ Geom2dHatch_Hatcher& IntTools_Context::Hatcher(const TopoDS_Face& aF) return *pHatcher; } +//======================================================================= +//function : OBB +//purpose : +//======================================================================= +IntTools_OBB& IntTools_Context::OBB(const TopoDS_Shape& aS, + const Standard_Real theFuzzy) +{ + Standard_Address anAdr; + IntTools_OBB* pBox; + // + if (!myOBBMap.IsBound(aS)) + { + pBox = (IntTools_OBB*)myAllocator->Allocate(sizeof(IntTools_OBB)); + new (pBox) IntTools_OBB(); + // + IntTools_OBB &aBox = *pBox; + IntTools_Tools::BuildOBB(aS, theFuzzy, aBox); + // + anAdr = (Standard_Address)pBox; + myOBBMap.Bind(aS, anAdr); + } + else + { + anAdr = myOBBMap.Find(aS); + pBox = (IntTools_OBB*)anAdr; + } + return *pBox; +} + //======================================================================= //function : SurfaceData //purpose : diff --git a/src/IntTools/IntTools_Context.hxx b/src/IntTools/IntTools_Context.hxx index 0da262e92e..923b784276 100644 --- a/src/IntTools/IntTools_Context.hxx +++ b/src/IntTools/IntTools_Context.hxx @@ -44,7 +44,7 @@ class gp_Pnt2d; class IntTools_Curve; class Bnd_Box; class TopoDS_Shape; - +class IntTools_OBB; //! The intersection Context contains geometrical //! and topological toolkit (classifiers, projectors, etc). @@ -98,6 +98,10 @@ Standard_EXPORT virtual ~IntTools_Context(); //! Returns a reference to surface adaptor for given face Standard_EXPORT BRepAdaptor_Surface& SurfaceAdaptor (const TopoDS_Face& theFace); + //! Returns a reference to surface adaptor for given face + Standard_EXPORT IntTools_OBB& OBB(const TopoDS_Shape& theShape, + const Standard_Real theFuzzy = Precision::Confusion()); + //! Computes the boundaries of the face using surface adaptor Standard_EXPORT void UVBounds (const TopoDS_Face& theFace, Standard_Real& UMin, @@ -250,6 +254,7 @@ protected: BOPCol_DataMapOfShapeAddress myProjSDataMap; BOPCol_DataMapOfShapeAddress myBndBoxDataMap; BOPCol_DataMapOfShapeAddress mySurfAdaptorMap; + BOPCol_DataMapOfShapeAddress myOBBMap; //! Map of oriented bounding boxes Standard_Integer myCreateFlag; Standard_Real myPOnSTolerance; diff --git a/src/IntTools/IntTools_OBB.cxx b/src/IntTools/IntTools_OBB.cxx new file mode 100644 index 0000000000..bd108bd4a6 --- /dev/null +++ b/src/IntTools/IntTools_OBB.cxx @@ -0,0 +1,125 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 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. + +#include + +#include + +// ======================================================================= +// function : IsOut +// purpose : +// ======================================================================= +Standard_Boolean IntTools_OBB::IsOut(const IntTools_OBB& theOther) const +{ + if (IsVoid() || theOther.IsVoid()) + return Standard_False; + + if (myIsAABox && theOther.myIsAABox) + { + // Both boxes are axis aligned - PMax points should be defined in this case. + // Use Bnd_B3d::IsOut method to check if the boxes are interfering + Bnd_B3d myB3d(myCenter, gp_Vec(myPMin, myCenter).XYZ()); + Bnd_B3d otherB3d(theOther.myCenter, gp_Vec(theOther.myPMin, theOther.myCenter).XYZ()); + return myB3d.IsOut(otherB3d); + } + + // According to the Separating Axis Theorem for Oriented Bounding Boxes + // it is necessary to check the 15 separating axes: + // - 6 axes of the boxes; + // - 9 cross products of the axes of the boxes. + // If any of these axes is valid, the boxes do not interfere. + + // The algorithm is following: + // 1. For the analyzed axis L: + // 2. Half of boxes vertices are projected onto the axis. + // 3. The projection segments for each box are computed. + // The length of the segment will be: + // Abs((HDimX*DirX).Dot(L)) + Abs((HDimY*DirY).Dot(L)) + Abs((HDimZ*DirZ).Dot(L)) + // 3. It is necessary to check if the distance between centers of the boxes + // projected onto the axis is more than the sum of the lengths + // of the projection segments: + // isOut = (theCenter2 - theCenter1).Dot(L) > (Length1 + Length2); + + + // Precomputed difference between centers + gp_XYZ D = theOther.myCenter - myCenter; + + // Check the axes of the this box, i.e. L is one of myAxes + // Since the Dot product of two of these directions is null, it could be skipped: + // myXDirection.Dot(myYDirection) = 0 + + for (Standard_Integer i = 0; i < 3; ++i) + { + // Length of the first segment + Standard_Real aLSegm1 = myHDims[i]; + + // Length of the second segment + Standard_Real aLSegm2 = 0; + for (Standard_Integer j = 0; j < 3; ++j) + aLSegm2 += Abs(theOther.myAxesMultiplied[j].Dot(myAxes[i])); + + // Distance between projected centers + Standard_Real aDistCC = Abs(D.Dot(myAxes[i])); + + if (aDistCC > aLSegm1 + aLSegm2) + return Standard_True; + } + + // Check the axes of the Other box, i.e. L is one of theOther.myAxes + + for (Standard_Integer i = 0; i < 3; ++i) + { + // Length of the first segment + Standard_Real aLSegm1 = 0.; + for (Standard_Integer j = 0; j < 3; ++j) + aLSegm1 += Abs(myAxesMultiplied[j].Dot(theOther.myAxes[i])); + + // Length of the second segment + Standard_Real aLSegm2 = theOther.myHDims[i]; + + // Distance between projected centers + Standard_Real aDistCC = Abs(D.Dot(theOther.myAxes[i])); + + if (aDistCC > aLSegm1 + aLSegm2) + return Standard_True; + } + + // Check the axes produced by the cross products + for (Standard_Integer i = 0; i < 3; ++i) + { + for (Standard_Integer j = 0; j < 3; ++j) + { + // Separating axis + gp_XYZ L = myAxes[i].Crossed(theOther.myAxes[j]); + + // Length of the first segment + Standard_Real aLSegm1 = 0.; + for (Standard_Integer k = 0; k < 3; ++k) + aLSegm1 += Abs(myAxesMultiplied[k].Dot(L)); + + // Length of the second segment + Standard_Real aLSegm2 = 0.; + for (Standard_Integer k = 0; k < 3; ++k) + aLSegm2 += Abs(theOther.myAxesMultiplied[k].Dot(L)); + + // Distance between projected centers + Standard_Real aDistCC = Abs(D.Dot(L)); + + if (aDistCC > aLSegm1 + aLSegm2) + return Standard_True; + } + } + + return Standard_False; +} diff --git a/src/IntTools/IntTools_OBB.hxx b/src/IntTools/IntTools_OBB.hxx new file mode 100644 index 0000000000..5eb28c2862 --- /dev/null +++ b/src/IntTools/IntTools_OBB.hxx @@ -0,0 +1,199 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 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 _IntTools_OBB_HeaderFile +#define _IntTools_OBB_HeaderFile + +#include +#include +#include +#include +#include + +#include +#include +#include + +//! The class describes the Oriented Bounding Box (OBB). +//! It is defined by a center of the box, the axes and the halves +//! of its three dimensions. +//! The OBB are used as a second step, after intersection of the +//! axes aligned boxes, for filtering the time-consuming interfering pairs +//! in Boolean Operations. +class IntTools_OBB +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Empty constructor + IntTools_OBB() + : + myIsAABox(Standard_False) + { + myHDims[0] = 0.; + myHDims[1] = 0.; + myHDims[2] = 0.; + } + + //! Constructor taking all defining parameters + IntTools_OBB(const gp_Pnt& theCenter, + const gp_Dir& theXDirection, + const gp_Dir& theYDirection, + const gp_Dir& theZDirection, + const Standard_Real theHXSize, + const Standard_Real theHYSize, + const Standard_Real theHZSize) + : + myCenter (theCenter.XYZ()), + myIsAABox(Standard_False) + { + myAxes[0] = theXDirection.XYZ(); + myAxes[1] = theYDirection.XYZ(); + myAxes[2] = theZDirection.XYZ(); + + myHDims[0] = theHXSize; + myHDims[1] = theHYSize; + myHDims[2] = theHZSize; + + myAxesMultiplied[0] = myAxes[0].Multiplied(myHDims[0]); + myAxesMultiplied[1] = myAxes[1].Multiplied(myHDims[1]); + myAxesMultiplied[2] = myAxes[2].Multiplied(myHDims[2]); + } + + //! Sets the center of OBB + void SetCenter(const gp_Pnt& theCenter) + { + myCenter = theCenter.XYZ(); + } + + //! Returns the center of OBB + const gp_XYZ& Center() const + { + return myCenter; + } + + //! Sets the X component of OBB - direction and size + void SetXComponent(const gp_Dir& theXDirection, + const Standard_Real theHXSize) + { + myAxes[0] = theXDirection.XYZ(); + myHDims[0] = theHXSize; + + myAxesMultiplied[0] = myAxes[0].Multiplied(myHDims[0]); + } + + //! Returns the X Direction of OBB + const gp_XYZ& XDirection() const + { + return myAxes[0]; + } + + //! Returns the X Dimension of OBB + Standard_Real HXSize() const + { + return myHDims[0]; + } + + //! Sets the Y component of OBB - direction and size + void SetYComponent(const gp_Dir& theYDirection, + const Standard_Real theHYSize) + { + myAxes[1] = theYDirection.XYZ(); + myHDims[1] = theHYSize; + + myAxesMultiplied[1] = myAxes[1].Multiplied(myHDims[1]); + } + + //! Returns the Y Direction of OBB + const gp_XYZ& YDirection() const + { + return myAxes[1]; + } + + //! Returns the Y Dimension of OBB + Standard_Real HYSize() const + { + return myHDims[1]; + } + + //! Sets the Z component of OBB - direction and size + void SetZComponent(const gp_Dir& theZDirection, + const Standard_Real theHZSize) + { + myAxes[2] = theZDirection.XYZ(); + myHDims[2] = theHZSize; + + myAxesMultiplied[2] = myAxes[2].Multiplied(myHDims[2]); + } + + //! Returns the Z Direction of OBB + const gp_XYZ& ZDirection() const + { + return myAxes[2]; + } + + //! Returns the Z Dimension of OBB + Standard_Real HZSize() const + { + return myHDims[2]; + } + + //! Checks if the box is empty. + Standard_Boolean IsVoid() const + { + return (((myHDims[0] + myHDims[1] + myHDims[2]) < gp::Resolution()) && !myIsAABox); + } + + //! Sets the flag for axes aligned box + void SetAABox(const Standard_Boolean& theFlag) + { + myIsAABox = theFlag; + } + + //! Returns TRUE if the box is axes aligned + Standard_Boolean IsAABox() const + { + return myIsAABox; + } + + //! Sets the min point + void SetMinPoint(const gp_Pnt& theMin) + { + myPMin = theMin.XYZ(); + } + + //! Returns the min point of the box + const gp_XYZ& MinPoint() const + { + return myPMin; + } + + //! Check if the box do not interfere the other box. + Standard_EXPORT Standard_Boolean IsOut(const IntTools_OBB& theOther) const; + +private: + + // OBB definition + gp_XYZ myCenter; //! Center of the OBB + gp_XYZ myAxes[3]; //! The axes of the box + Standard_Real myHDims[3]; //! Half-size dimensions of the OBB + + gp_XYZ myAxesMultiplied[3]; //! Multiplied axes to avoid their recalculation in IsOut method + + Standard_Boolean myIsAABox; //! To be set if the OBB is axis aligned box; + gp_XYZ myPMin; //! Min point of the box. +}; + +#endif diff --git a/src/IntTools/IntTools_Tools.cxx b/src/IntTools/IntTools_Tools.cxx index 46c891d395..9aa753db37 100644 --- a/src/IntTools/IntTools_Tools.cxx +++ b/src/IntTools/IntTools_Tools.cxx @@ -56,6 +56,18 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_OBB +#include +#endif + static void ParabolaTolerance(const Handle(Geom_Curve)& , const Standard_Real , @@ -840,3 +852,113 @@ Standard_Real IntTools_Tools::ComputeIntRange(const Standard_Real theTol1, // return aDt; } + +//======================================================================= +// Function : BuildOBB +// purpose : +//======================================================================= +void IntTools_Tools::BuildOBB(const TopoDS_Shape& theS, + const Standard_Real theFuzzy, + IntTools_OBB& theOBB) +{ + // Compute the transformation matrix to obtain more tight bounding box + GProp_GProps G; + switch (theS.ShapeType()) + { + case TopAbs_VERTEX: + { + // Just make the AA box + const gp_Pnt& aP = BRep_Tool::Pnt(TopoDS::Vertex(theS)); + Bnd_Box aBox; + aBox.Add(aP); + aBox.SetGap(BRep_Tool::Tolerance(TopoDS::Vertex(theS)) + theFuzzy); + + theOBB.SetCenter(aP); + theOBB.SetXComponent(gp_Dir(1, 0, 0), aBox.GetGap()); + theOBB.SetYComponent(gp_Dir(0, 1, 0), aBox.GetGap()); + theOBB.SetZComponent(gp_Dir(0, 0, 1), aBox.GetGap()); + + theOBB.SetAABox(Standard_True); + theOBB.SetMinPoint(aBox.CornerMin()); + return; + } + case TopAbs_EDGE: + BRepGProp::LinearProperties(theS, G, Standard_True); + break; + case TopAbs_FACE: + BRepGProp::SurfaceProperties(theS, G, Standard_True); + break; + case TopAbs_SOLID: + BRepGProp::VolumeProperties(theS, G, Standard_True); + break; + default: + break; + } + + // Coordinate system in which the shape will have the optimal bounding box + gp_Ax3 aLocCoordSys(G.CentreOfMass(), + G.PrincipalProperties().ThirdAxisOfInertia(), + G.PrincipalProperties().FirstAxisOfInertia()); + + // Transform the shape to the local coordinate system + gp_Trsf aTrsf; + aTrsf.SetTransformation(aLocCoordSys); + + BRepBuilderAPI_Transform aTransformer(theS, aTrsf); + if (aTransformer.IsDone()) + { + const TopoDS_Shape& aST = aTransformer.Shape(); + + // Build the bounding box for oriented shape + Bnd_Box anOBB; + BRepBndLib::Add(aST, anOBB); + anOBB.SetGap(theFuzzy); + + // Create the OBB box + gp_Pnt aPMin = anOBB.CornerMin(); + gp_Pnt aPMax = anOBB.CornerMax(); + + // Compute the center of the box + gp_XYZ aCenter = (aPMin.XYZ() + aPMax.XYZ()) / 2.; + aTrsf.Inverted().Transforms(aCenter); + + // Compute the half diagonal size of the box + gp_XYZ anOBBHSize = (aPMax.XYZ() - aPMin.XYZ()) / 2.; + // Make transformation + const Standard_Real * aMat = &aTrsf.Inverted().HVectorialPart().Value(1, 1); + // Compute axes directions of the box + gp_XYZ aXDir(aMat[0], aMat[3], aMat[6]); + gp_XYZ aYDir(aMat[1], aMat[4], aMat[7]); + gp_XYZ aZDir(aMat[2], aMat[5], aMat[8]); + + theOBB.SetCenter(aCenter); + theOBB.SetXComponent(aXDir, anOBBHSize.X()); + theOBB.SetYComponent(aYDir, anOBBHSize.Y()); + theOBB.SetZComponent(aZDir, anOBBHSize.Z()); + + gp_XYZ aPMinXYZ = aPMin.XYZ(); + aTrsf.Inverted().Transforms(aPMinXYZ); + theOBB.SetMinPoint(aPMinXYZ); +#ifdef DEBUG_OBB + // Get the obtained box + GetOBBShapeBox(theOBB); +#endif + } +} + + +#ifdef DEBUG_OBB +//======================================================================= +// Function : GetOBBShapeBox +// purpose : +//======================================================================= +TopoDS_Shape IntTools_Tools::GetOBBShapeBox(const IntTools_OBB& theOBB) +{ + gp_Ax2 axis(theOBB.MinPoint(), theOBB.ZDirection()); + axis.SetXDirection(theOBB.XDirection()); + BRepPrimAPI_MakeBox aSMaker(axis, 2 * theOBB.HXSize(), 2 * theOBB.HYSize(), 2 * theOBB.HZSize()); + const TopoDS_Shape& aSolid = aSMaker.Solid(); + + return aSolid; +} +#endif diff --git a/src/IntTools/IntTools_Tools.hxx b/src/IntTools/IntTools_Tools.hxx index 5e828548a0..dbd4557cc1 100644 --- a/src/IntTools/IntTools_Tools.hxx +++ b/src/IntTools/IntTools_Tools.hxx @@ -42,7 +42,7 @@ class gp_Lin; class gp_Pln; class Geom2d_Curve; class Geom_Surface; - +class IntTools_OBB; //! The class contains handy static functions @@ -183,6 +183,16 @@ public: const Standard_Real theAngle); + //! Computes the Oriented Bounding box for the shape + Standard_EXPORT static void BuildOBB(const TopoDS_Shape& theS, + const Standard_Real theFuzzy, + IntTools_OBB& theOBB); + +#ifdef DEBUG_OBB + //! Get the solid built from the OBB box + Standard_EXPORT static TopoDS_Shape GetOBBShapeBox(const IntTools_OBB& theOBB); +#endif + protected: -- 2.39.5