diff --git a/src/BOPAlgo/BOPAlgo.msg b/src/BOPAlgo/BOPAlgo.msg index 67350fca88..5781edecfe 100644 --- a/src/BOPAlgo/BOPAlgo.msg +++ b/src/BOPAlgo/BOPAlgo.msg @@ -67,3 +67,6 @@ Warning: Removal of internal boundaries among Faces has failed .BOPAlgo_AlertRemovalOfIBForEdgesFailed Warning: Removal of internal boundaries among Edges has failed + +.BOPAlgo_AlertSolidBuilderUnusedFaces +Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation diff --git a/src/BOPAlgo/BOPAlgo_Alerts.hxx b/src/BOPAlgo/BOPAlgo_Alerts.hxx index 02cec15f8f..0a84126779 100644 --- a/src/BOPAlgo/BOPAlgo_Alerts.hxx +++ b/src/BOPAlgo/BOPAlgo_Alerts.hxx @@ -78,4 +78,7 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertShellSplitterFailed) //! Some edges are too small and have no valid range DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertTooSmallEdge) +//! Some of the faces passed to the Solid Builder algorithm have not been classified +//! and not used for solids creation +DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertSolidBuilderUnusedFaces) #endif // _BOPAlgo_Alerts_HeaderFile diff --git a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx index fa19419e77..12669b7771 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx +++ b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -127,127 +128,7 @@ typedef NCollection_DataMap // typedef BOPAlgo_DataMapOfIntegerBSSB::Iterator BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB; -// -//======================================================================= -//function : BOPAlgo_FacePnt -//purpose : -//======================================================================= -class BOPAlgo_FacePnt { - public: - BOPAlgo_FacePnt() { - } - // - virtual ~BOPAlgo_FacePnt() { - } - // - void SetFace(const TopoDS_Face& aFace) { - myFace=aFace; - } - // - const TopoDS_Face& Face()const { - return myFace; - } - // - void SetPnt(const gp_Pnt& aPnt) { - myPnt=aPnt; - } - // - const gp_Pnt& Pnt()const { - return myPnt; - } - // - protected: - gp_Pnt myPnt; - TopoDS_Face myFace; -}; -// -typedef BOPCol_NCVector - BOPAlgo_VectorOfFacePnt; -// -//======================================================================= -//function : BOPAlgo_FaceSolid -//purpose : -//======================================================================= -class BOPAlgo_FaceSolid : public BOPAlgo_Algo { - public: - DEFINE_STANDARD_ALLOC - BOPAlgo_FaceSolid() : - myIsInternalFace(Standard_False) { - } - // - virtual ~BOPAlgo_FaceSolid() { - } - // - void SetFace(const TopoDS_Face& aFace) { - myFace=aFace; - } - // - const TopoDS_Face& Face()const { - return myFace; - } - // - void SetSolid(const TopoDS_Solid& aSolid) { - mySolid=aSolid; - } - // - const TopoDS_Solid& Solid()const { - return mySolid; - } - // - void SetPnt(const gp_Pnt& aPnt) { - myPnt=aPnt; - } - // - const gp_Pnt& Pnt()const { - return myPnt; - } - void SetContext(const Handle(IntTools_Context)& aContext) { - myContext=aContext; - } - // - const Handle(IntTools_Context)& Context()const { - return myContext; - } - // - Standard_Boolean IsInternalFace() const { - return myIsInternalFace; - } - // - virtual void Perform () { - TopAbs_State aState; - // - BOPAlgo_Algo::UserBreak(); - // - aState=BOPTools_AlgoTools::ComputeState(myPnt, mySolid, - Precision::Confusion(), - myContext); - // - myIsInternalFace=(aState==TopAbs_IN); - } - // - protected: - Standard_Boolean myIsInternalFace; - gp_Pnt myPnt; - TopoDS_Face myFace; - TopoDS_Solid mySolid; - Handle(IntTools_Context) myContext; -}; -//======================================================================= -typedef BOPCol_NCVector - BOPAlgo_VectorOfFaceSolid; -// -typedef BOPCol_ContextFunctor - BOPAlgo_FaceSolidFunctor; -// -typedef BOPCol_ContextCnt - BOPAlgo_FaceSolidCnt; -// //======================================================================= //======================================================================= @@ -766,49 +647,29 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes() return; } // - Standard_Boolean bIsInternalFace; - Standard_Integer k, aNbVFS, aNbSLF, aNbVFP, aNbA; BRep_Builder aBB; - TopoDS_Iterator aIt; - TopExp_Explorer aExp; BOPCol_ListIteratorOfListOfShape aItLS; BOPCol_IndexedMapOfShape aMFs; BOPCol_ListOfShape aLSI; - BOPAlgo_VectorOfFaceSolid aVFS; - BOPAlgo_VectorOfFacePnt aVFP; BOPCol_ListIteratorOfListOfInteger aItLI; - BOPCol_BoxBndTreeSelector aSelector; - BOPCol_BoxBndTree aBBTree; - NCollection_UBTreeFiller - aTreeFiller(aBBTree); // - aNbA=myAreas.Extent(); + Standard_Integer aNbA = myAreas.Extent(); // - // 1. aVFP + // Fill Tree with boxes aItLS.Initialize(myLoopsInternal); for (; aItLS.More(); aItLS.Next()) { const TopoDS_Shape& aShell=aItLS.Value(); - aIt.Initialize(aShell); + TopoDS_Iterator aIt(aShell); for (; aIt.More(); aIt.Next()) { const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value()); // - if (!aMFs.Contains(aF)) { + if (!aMFs.Contains(aF)) + { aMFs.Add(aF); - // - gp_Pnt aP; - gp_Pnt2d aP2D; - // - if (aNbA) { - BOPTools_AlgoTools3D::PointInFace(aF, aP, aP2D, myContext); - } - // - BOPAlgo_FacePnt& aFP=aVFP.Append1(); - aFP.SetFace(aF); - aFP.SetPnt(aP); } } } - // + if (!aNbA) { // 7b. "Rest" faces treatment TopoDS_Solid aSolid; @@ -826,146 +687,81 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes() return; // => }//if (!aNbA) { // - // 2. Prepare TreeFiller - aNbVFP=aVFP.Extent(); - for(k=0; k // +#include #include // #include @@ -43,9 +44,13 @@ #include #include // +#include +// #include #include +#include #include +#include #include #include #include @@ -131,367 +136,6 @@ class BOPAlgo_ShapeBox { typedef BOPCol_NCVector BOPAlgo_VectorOfShapeBox; // //======================================================================= -// class: BOPAlgo_FillIn3DParts -// -//======================================================================= -//class : BOPAlgo_FillIn3DParts -//purpose : -//======================================================================= -class BOPAlgo_FillIn3DParts : public BOPAlgo_Algo { - public: - DEFINE_STANDARD_ALLOC - - BOPAlgo_FillIn3DParts(){ - myHasImage=Standard_False; - myBBTree=NULL; - myVSB=NULL; - }; - // - virtual ~BOPAlgo_FillIn3DParts(){ - }; - // - void SetSolid(const TopoDS_Solid& aS) { - mySolid=aS; - }; - // - const TopoDS_Solid& Solid()const { - return mySolid; - }; - // - void SetDraftSolid(const TopoDS_Solid& aS) { - myDraftSolid=aS; - }; - // - const TopoDS_Solid& DraftSolid()const { - return myDraftSolid; - }; - // - void SetHasImage(const Standard_Boolean bFlag) { - myHasImage=bFlag; - }; - // - Standard_Boolean HasImage()const { - return myHasImage; - }; - // - void SetBoxS(const Bnd_Box& aBox) { - myBoxS=aBox; - }; - // - const Bnd_Box& BoxS()const { - return myBoxS; - }; - // - void SetLIF(const BOPCol_ListOfShape& aLIF) { - myLIF=aLIF; - }; - // - const BOPCol_ListOfShape& LIF()const { - return myLIF; - }; - // - void SetBBTree(const BOPCol_BoxBndTree& aBBTree) { - myBBTree=(BOPCol_BoxBndTree*)&aBBTree; - }; - // - void SetVSB(const BOPAlgo_VectorOfShapeBox& aVSB) { - myVSB=(BOPAlgo_VectorOfShapeBox*)&aVSB; - }; - // - // - void SetContext(const Handle(IntTools_Context)& aContext) { - myContext=aContext; - } - // - const Handle(IntTools_Context)& Context()const { - return myContext; - } - // - virtual void Perform(); - // - - // - const BOPCol_ListOfShape& LFIN()const { - return myLFIN; - }; - - protected: - void MapEdgesAndFaces - (const TopoDS_Shape& , - BOPCol_IndexedDataMapOfShapeListOfShape& , - const Handle(NCollection_BaseAllocator)& ); - - void MakeConnexityBlock - (const BOPCol_ListOfShape& , - const BOPCol_IndexedMapOfShape& , - const BOPCol_MapOfShape& , - const BOPCol_IndexedDataMapOfShapeListOfShape& , - BOPCol_ListOfShape& , - const Handle(NCollection_BaseAllocator)& ); - // - protected: - TopoDS_Solid mySolid; - TopoDS_Solid myDraftSolid; - Standard_Boolean myHasImage; - Bnd_Box myBoxS; - BOPCol_ListOfShape myLIF; - BOPCol_ListOfShape myLFIN; - // - BOPCol_BoxBndTree* myBBTree; - BOPAlgo_VectorOfShapeBox* myVSB; - // - TopoDS_Iterator myItF; - TopoDS_Iterator myItW; - - Handle(IntTools_Context) myContext; -}; - -//======================================================================= -//function : BOPAlgo_FillIn3DParts::Perform -//purpose : -//======================================================================= -void BOPAlgo_FillIn3DParts::Perform() -{ - Handle(NCollection_BaseAllocator) aAlr1; - BOPAlgo_Algo::UserBreak(); - // - Standard_Integer aNbFP, k, nFP, iIsIN; - Standard_Real aTolPC; - BOPCol_ListIteratorOfListOfInteger aItLI, aItLI1; - BOPCol_ListIteratorOfListOfShape aItLS; - BOPCol_BoxBndTreeSelector aSelector; - // - aAlr1= - NCollection_BaseAllocator::CommonBaseAllocator(); - // - BOPCol_ListOfShape aLFP(aAlr1); - BOPCol_ListOfShape aLCBF(aAlr1); - BOPCol_MapOfShape aMFDone(100, aAlr1); - BOPCol_IndexedMapOfShape aME(100, aAlr1); - BOPCol_IndexedMapOfShape aMF(100, aAlr1); - BOPCol_IndexedDataMapOfShapeListOfShape aMEFP(100, aAlr1); - BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, aAlr1); - // - aTolPC=Precision::Confusion(); - myLFIN.Clear(); - BOPAlgo_VectorOfShapeBox& aVSB=*myVSB; - // - // 1. aMEF - EF map for myDraftSolid - BOPTools::MapShapesAndAncestors(myDraftSolid, - TopAbs_EDGE, - TopAbs_FACE, - aMEF); - - // - // 2. Faces from myDraftSolid and its own internal faces => aMF - BOPTools::MapShapes(myDraftSolid, TopAbs_FACE, aMF); - aItLS.Initialize(myLIF); - for (; aItLS.More(); aItLS.Next()) { - const TopoDS_Shape& aFI=aItLS.Value(); - aMF.Add(aFI); - } - // aME - Edges from DraftSolid [i.e. edges to stop] - BOPTools::MapShapes(myDraftSolid, TopAbs_EDGE, aME); - // - // 3. Select boxes of faces that are not out of aBoxS - aSelector.Clear(); - aSelector.SetBox(myBoxS); - // - aNbFP=myBBTree->Select(aSelector); - const BOPCol_ListOfInteger& aLIFPx=aSelector.Indices(); - // - // 4. aIVec, aLIFP - faces to process - BOPCol_ListOfInteger aLIFP(aAlr1); - BOPCol_NCVector aIVec(256, aAlr1); - // - k=0; - aItLI.Initialize(aLIFPx); - for (; aItLI.More(); aItLI.Next()) { - nFP=aItLI.Value(); - const TopoDS_Shape& aFP=aVSB(nFP).Shape(); - if (!aMF.Contains(aFP)) { - MapEdgesAndFaces(aFP, aMEFP, aAlr1); - aLIFP.Append(nFP); - aIVec.Append1()=nFP; - ++k; - } - } - aNbFP=k; - // - // sort indices - std::sort(aIVec.begin(), aIVec.end()); - // - // 5. Collect faces that are IN mySolid [ myLFIN ] - for (k=0; k \ - BOPAlgo_VectorOfFillIn3DParts; -// -typedef BOPCol_ContextFunctor - BOPCol_FillIn3DPartsFunctor; -// -typedef BOPCol_ContextCnt - BOPAlgo_FillIn3DPartsCnt; -// -//======================================================================= // class: BOPAlgo_Builder // //======================================================================= @@ -540,156 +184,123 @@ void BOPAlgo_Builder::FillIn3DParts BOPCol_DataMapOfShapeShape& theDraftSolids, const BOPCol_BaseAllocator& ) { - Standard_Boolean bHasImage; - Standard_Integer i, k, aNbS, aNbLIF, aNbFIN, aNbVSB, aNbVFIP; - Handle(NCollection_BaseAllocator) aAlr0; - TopoDS_Solid aSD; - TopoDS_Iterator aIt; - BRep_Builder aBB; - // - BOPCol_ListIteratorOfListOfInteger aItLI, aItLI1; - BOPCol_ListIteratorOfListOfShape aItLS; - // - aAlr0= - NCollection_BaseAllocator::CommonBaseAllocator(); - // - BOPCol_MapOfShape aMFence(100, aAlr0); - BOPAlgo_VectorOfShapeBox aVSB(256, aAlr0); - // - theDraftSolids.Clear(); - // - // 1. aVSB vector Index/FaceBox - aNbS=myDS->NbSourceShapes(); - for (i=0; iShapeInfo(i); - if (aSI.ShapeType()!=TopAbs_FACE) { + Handle(NCollection_BaseAllocator) anAlloc = new NCollection_IncAllocator; + + // Find all faces that are IN solids + + // Store boxes of the shapes into a map + BOPCol_IndexedDataMapOfShapeBox aShapeBoxMap(1, anAlloc); + + // Fence map + BOPCol_MapOfShape aMFence(1, anAlloc); + + // Get all faces + TopTools_ListOfShape aLFaces(anAlloc); + + Standard_Integer i, aNbS = myDS->NbSourceShapes(); + for (i = 0; i < aNbS; ++i) + { + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); + if (aSI.ShapeType() != TopAbs_FACE) continue; - } - // - const TopoDS_Shape& aS=aSI.Shape(); - // - if (myImages.IsBound(aS)) { - const BOPCol_ListOfShape& aLS=myImages.Find(aS); - aItLS.Initialize(aLS); - for (; aItLS.More(); aItLS.Next()) { - const TopoDS_Shape& aSx=aItLS.Value(); - if (!aMFence.Add(aSx)) { - continue; - } - Bnd_Box aBox; - BRepBndLib::Add(aSx, aBox); - aBox.SetGap(aBox.GetGap() + Precision::Confusion()); - // - BOPAlgo_ShapeBox& aSB=aVSB.Append1(); - aSB.SetShape(aSx); - aSB.SetBox(aBox); + + const TopoDS_Shape& aS = aSI.Shape(); + const TopTools_ListOfShape* pLSIm = myImages.Seek(aS); + + if (pLSIm) + { + TopTools_ListIteratorOfListOfShape aItLSIm(*pLSIm); + for (; aItLSIm.More(); aItLSIm.Next()) + { + const TopoDS_Shape& aSIm = aItLSIm.Value(); + if (aMFence.Add(aSIm)) + aLFaces.Append(aSIm); } } - else { - const Bnd_Box& aBox=aSI.Box(); - // - BOPAlgo_ShapeBox& aSB=aVSB.Append1(); - aSB.SetShape(aS); - aSB.SetBox(aBox); + else + { + aLFaces.Append(aS); + aShapeBoxMap.Add(aS, aSI.Box()); } - }//for (i=0; i - aTreeFiller(aBBTree); - // - aNbVSB=aVSB.Extent(); - for (k=0; kShapeInfo(i); - if (aSI.ShapeType()!=TopAbs_SOLID) { + + BRep_Builder aBB; + + // Get all solids + TopTools_ListOfShape aLSolids(anAlloc); + // Keep INTERNAL faces of the solids + BOPCol_DataMapOfShapeListOfShape aSolidsIF(1, anAlloc); + // Draft solids + BOPCol_IndexedDataMapOfShapeShape aDraftSolid(1, anAlloc); + + for (i = 0; i < aNbS; ++i) + { + BOPDS_ShapeInfo& aSI = myDS->ChangeShapeInfo(i); + if (aSI.ShapeType() != TopAbs_SOLID) continue; - } - // - const TopoDS_Shape& aS=aSI.Shape(); - const TopoDS_Solid& aSolid=(*(TopoDS_Solid*)(&aS)); - // - // 2.0 Flag bHasImage - bHasImage=Standard_False; - aIt.Initialize(aS); - for (; aIt.More(); aIt.Next()) { - const TopoDS_Shape& aShell=aIt.Value(); - bHasImage=myImages.IsBound(aShell); - if (bHasImage){ - break; - } - } - // - // 2.1 Bounding box for the solid aS [ aBoxS ] - Bnd_Box aBoxS; - aBoxS=aSI.Box(); - // - // 2.2 Build Draft Solid [aSD] - BOPCol_ListOfShape aLIF; + + const TopoDS_Shape& aS = aSI.Shape(); + const TopoDS_Solid& aSolid = (*(TopoDS_Solid*)(&aS)); // + // Bounding box for the solid aS + const Bnd_Box& aBoxS = aSI.Box(); + + // Build Draft Solid + TopTools_ListOfShape aLIF; + TopoDS_Solid aSD; aBB.MakeSolid(aSD); BuildDraftSolid(aSolid, aSD, aLIF); - // - BOPAlgo_FillIn3DParts& aFIP=aVFIP.Append1(); - // - aFIP.SetSolid(aSolid); - aFIP.SetDraftSolid(aSD); - aFIP.SetHasImage(bHasImage); - aFIP.SetBoxS(aBoxS); - aFIP.SetLIF(aLIF); - aFIP.SetBBTree(aBBTree); - aFIP.SetVSB(aVSB); - }//for (i=0; iAppend(aItLS.Value()); + + aItLS.Initialize(aLInternal); + for (; aItLS.More(); aItLS.Next()) + pLIN->Append(aItLS.Value()); } } } diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx index 5867221f5e..1b4ef844a7 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx @@ -54,7 +54,8 @@ BOPAlgo_PaveFiller::BOPAlgo_PaveFiller() BOPAlgo_PaveFiller::BOPAlgo_PaveFiller (const Handle(NCollection_BaseAllocator)& theAllocator) : - BOPAlgo_Algo(theAllocator) + BOPAlgo_Algo(theAllocator), + myFPBDone(1, theAllocator) { myDS = NULL; myIterator = NULL; @@ -286,6 +287,13 @@ void BOPAlgo_PaveFiller::PerformInternal() UpdatePaveBlocksWithSDVertices(); UpdateInterfsWithSDVertices(); // + // Force intersection of edges after increase + // of the tolerance values of their vertices + //ForceInterfEE(); + // Force Edge/Face intersection after increase + // of the tolerance values of their vertices + ForceInterfEF(); + // // 22 PerformFF(); if (HasErrors()) { diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.hxx b/src/BOPAlgo/BOPAlgo_PaveFiller.hxx index ab79f4ec98..c34565a816 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.hxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.hxx @@ -167,6 +167,9 @@ protected: Bnd_Box, TColStd_MapTransientHasher> BOPAlgo_DataMapOfPaveBlockBndBox; + typedef NCollection_DataMap + BOPAlgo_DataMapOfIntegerMapOfPaveBlock; //! Sets non-destructive mode automatically if an argument //! contains a locked sub-shape (see TopoDS_Shape::Locked()). @@ -474,6 +477,19 @@ protected: //! In case self-interference is found the warning is added. Standard_EXPORT void CheckSelfInterference(); + //! The method looks for the additional common blocks among pairs of edges + //! with the same bounding vertices. + Standard_EXPORT void ForceInterfEE(); + + //! The method looks for the additional edge/face common blocks + //! among pairs of edge/face having the same vertices. + Standard_EXPORT void ForceInterfEF(); + + //! Performs intersection of given pave blocks + //! with all faces from arguments. + Standard_EXPORT void ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB, + const Standard_Boolean theAddInterf); + BOPCol_ListOfShape myArguments; BOPDS_PDS myDS; @@ -485,6 +501,8 @@ protected: Standard_Boolean myAvoidBuildPCurve; BOPAlgo_GlueEnum myGlue; + BOPAlgo_DataMapOfIntegerMapOfPaveBlock myFPBDone; //!< Fence map of intersected faces and pave blocks + private: diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx index 3a8892e0be..159411df7f 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx @@ -768,3 +768,278 @@ Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE, } return bValid; } + +#include +#include + +//======================================================================= +//function : ForceInterfEE +//purpose : +//======================================================================= +void BOPAlgo_PaveFiller::ForceInterfEE() +{ + // Now that we have vertices increased and unified, try to find additional + // common blocks among the pairs of edges. + // Since all real intersections should have already happened, here we + // are interested in common blocks only, thus we need to check only + // those pairs of pave blocks with the same bounding vertices. + + Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; + + // Initialize pave blocks for all vertices which participated in intersections + const Standard_Integer aNbS = myDS->NbSourceShapes(); + for (Standard_Integer i = 0; i < aNbS; ++i) + { + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); + if (aSI.ShapeType() == TopAbs_VERTEX) + { + if (myDS->HasInterf(i)) + myDS->InitPaveBlocksForVertex(i); + } + } + + // Fill the connection map from bounding vertices to pave blocks + // having those bounding vertices + NCollection_IndexedDataMap aPBMap(1, anAlloc); + // Fence map of pave blocks + BOPDS_MapOfPaveBlock aMPBFence(1, anAlloc); + + for (Standard_Integer i = 0; i < aNbS; ++i) + { + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); + if (aSI.ShapeType() != TopAbs_EDGE) + // Not an edge + continue; + + if (!aSI.HasReference()) + // Edge has no pave blocks + continue; + + if (aSI.HasFlag()) + // Degenerated edge + continue; + + const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(i); + BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB); + for (; aItLPB.More(); aItLPB.Next()) + { + const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value(); + const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB); + if (!aMPBFence.Add(aPBR)) + continue; + + // Get indices + Standard_Integer nV1, nV2; + aPBR->Indices(nV1, nV2); + + // Add pave block to a map + BOPDS_Pair aPair(nV1, nV2); + BOPDS_ListOfPaveBlock *pList = aPBMap.ChangeSeek(aPair); + if (!pList) + pList = &aPBMap(aPBMap.Add(aPair, BOPDS_ListOfPaveBlock(anAlloc))); + pList->Append(aPBR); + } + } + + Standard_Integer aNbPB = aPBMap.Extent(); + if (!aNbPB) + return; + + const Standard_Boolean bSICheckMode = (myArguments.Extent() == 1); + + // Prepare pave blocks with the same vertices for intersection. + BOPAlgo_VectorOfEdgeEdge aVEdgeEdge; + + for (Standard_Integer i = 1; i <= aNbPB; ++i) + { + const BOPDS_ListOfPaveBlock& aLPB = aPBMap(i); + if (aLPB.Extent() < 2) + continue; + + const BOPDS_Pair& aPair = aPBMap.FindKey(i); + Standard_Integer nV1, nV2; + aPair.Indices(nV1, nV2); + + const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1)); + const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2)); + + // Use the max tolerance of vertices as Fuzzy value for intersection of edges. + // In the Self-Interference check mode we are interested in real + // intersections only, so use only the real tolerance of edges, + // no need to use the extended tolerance. + Standard_Real aTolAdd = (bSICheckMode ? myFuzzyValue : + 2 * Max(BRep_Tool::Tolerance(aV1), BRep_Tool::Tolerance(aV2))); + + // All possible pairs combined from the list should be checked + BOPDS_ListIteratorOfListOfPaveBlock aItLPB1(aLPB); + for (; aItLPB1.More(); aItLPB1.Next()) + { + const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value(); + const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPB1); + const Standard_Integer nE1 = aPB1->OriginalEdge(); + const Standard_Integer iR1 = myDS->Rank(nE1); + const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1)); + Standard_Real aT11, aT12; + aPB1->Range(aT11, aT12); + BRepAdaptor_Curve aBAC1(aE1); + gp_Pnt aPm; + gp_Vec aVTgt1; + aBAC1.D1((aT11 + aT12) * 0.5, aPm, aVTgt1); + if (aVTgt1.SquareMagnitude() < gp::Resolution()) + continue; + aVTgt1.Normalize(); + + BOPDS_ListIteratorOfListOfPaveBlock aItLPB2 = aItLPB1; + for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next()) + { + const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value(); + const Handle(BOPDS_CommonBlock)& aCB2 = myDS->CommonBlock(aPB2); + const Standard_Integer nE2 = aPB2->OriginalEdge(); + const Standard_Integer iR2 = myDS->Rank(nE2); + + // Check that the edges came from different arguments + if (iR1 == iR2) + { + // If the sharing of the vertices is not original, but has been acquired + // during the operation, check the coincidence of the edges even if + // they came from the same argument + if ((!myDS->IsNewShape(nV1) && (myDS->Rank(nV1) == iR1)) || + (!myDS->IsNewShape(nV2) && (myDS->Rank(nV2) == iR2))) + continue; + } + + // Check that the Pave blocks do not form the Common block already + if (!aCB1.IsNull() && !aCB2.IsNull()) + { + if (aCB1 == aCB2) + continue; + } + + const TopoDS_Edge& aE2 = TopoDS::Edge(myDS->Shape(nE2)); + Standard_Real aT21, aT22; + aPB2->Range(aT21, aT22); + + // Check the angle between edges in the middle point. + // If the angle is more than 10 degrees, do not use the additional + // tolerance, as it may lead to undesired unification of edges + Standard_Boolean bUseAddTol = Standard_True; + { + BRepAdaptor_Curve aBAC2(aE2); + if (aBAC1.GetType() != GeomAbs_Line || + aBAC2.GetType() != GeomAbs_Line) + { + GeomAPI_ProjectPointOnCurve& aProjPC = myContext->ProjPC(aE2); + aProjPC.Perform(aPm); + if (!aProjPC.NbPoints()) + continue; + + gp_Pnt aPm2; + gp_Vec aVTgt2; + aBAC2.D1(aProjPC.LowerDistanceParameter(), aPm2, aVTgt2); + if (aVTgt2.SquareMagnitude() < gp::Resolution()) + continue; + + // The angle should be close to zero + Standard_Real aCos = aVTgt1.Dot (aVTgt2.Normalized()); + if (Abs(aCos) < 0.9848) + bUseAddTol = Standard_False; + } + } + + // Add pair for intersection + BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge.Append1(); + anEdgeEdge.UseQuickCoincidenceCheck(Standard_True); + anEdgeEdge.SetPaveBlock1(aPB1); + anEdgeEdge.SetPaveBlock2(aPB2); + anEdgeEdge.SetEdge1(aE1, aT11, aT12); + anEdgeEdge.SetEdge2(aE2, aT21, aT22); + //anEdgeEdge.SetBoxes (myDS->ShapeInfo(nE1).Box(), myDS->ShapeInfo (nE2).Box()); + if (bUseAddTol) + anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd); + else + anEdgeEdge.SetFuzzyValue(myFuzzyValue); + anEdgeEdge.SetProgressIndicator(myProgressIndicator); + } + } + } + + Standard_Integer aNbPairs = aVEdgeEdge.Length(); + if (!aNbPairs) + return; + + aPBMap.Clear(); + aMPBFence.Clear(); + anAlloc->Reset(); + + // Perform intersection of the found pairs + BOPAlgo_EdgeEdgeCnt::Perform (myRunParallel, aVEdgeEdge); + + BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE(); + if (aEEs.IsEmpty()) + aEEs.SetIncrement(10); + + // Analyze the results of intersection looking for TopAbs_EDGE + // intersection type only. + + BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(1, anAlloc); + + for (Standard_Integer i = 0; i < aNbPairs; ++i) + { + BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge(i); + if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors()) + { + // Warn about failed intersection of sub-shapes + //const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge()); + //const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge()); + //AddIntersectionFailedWarning(aE1, aE2); + continue; + } + + const IntTools_SequenceOfCommonPrts& aCParts = anEdgeEdge.CommonParts(); + if (aCParts.Length() != 1) + continue; + + const IntTools_CommonPrt& aCP = aCParts(1); + if (aCP.Type() != TopAbs_EDGE) + continue; + + Handle(BOPDS_PaveBlock) aPB[] = {anEdgeEdge.PaveBlock1(), anEdgeEdge.PaveBlock2()}; + const Standard_Integer nE1 = aPB[0]->OriginalEdge(); + const Standard_Integer nE2 = aPB[1]->OriginalEdge(); + + if (myDS->Rank(nE1) == myDS->Rank(nE2)) + { + // Add acquired self-interference warning + //TopoDS_Compound aWC; + //BRep_Builder().MakeCompound(aWC); + //BRep_Builder().Add(aWC, myDS->Shape(nE1)); + //BRep_Builder().Add(aWC, myDS->Shape(nE2)); + //AddWarning(new BOPAlgo_AlertAcquiredSelfIntersection(aWC)); + } + + BOPDS_InterfEE& aEE = aEEs.Append1(); + aEE.SetIndices(nE1, nE2); + aEE.SetCommonPart(aCP); + myDS->AddInterf(nE1, nE2); + + // Fill map for common blocks creation + for (Standard_Integer j = 0; j < 2; ++j) + { + if (myDS->IsCommonBlock(aPB[j])) + { + const BOPDS_ListOfPaveBlock& aLPBCB = myDS->CommonBlock(aPB[j])->PaveBlocks(); + BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB); + for (; aItLPB.More(); aItLPB.Next()) + BOPAlgo_Tools::FillMap(aPB[j], aItLPB.Value(), aMPBLPB, anAlloc); + } + } + BOPAlgo_Tools::FillMap(aPB[0], aPB[1], aMPBLPB, anAlloc); + } + + // Create new common blocks of coinciding pairs. + BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, anAlloc, myDS); +} diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx index 84fc6d10d0..6373b3ba11 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -33,9 +34,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -43,12 +46,15 @@ #include #include #include +#include +#include #include #include #include #include #include + //======================================================================= //class : BOPAlgo_EdgeFace //purpose : @@ -247,7 +253,12 @@ void BOPAlgo_PaveFiller::PerformEF() BOPTools_AlgoTools::CorrectRange(aE, aF, aSR, aPBRange); aEdgeFace.SetRange (aPBRange); aEdgeFace.SetProgressIndicator(myProgressIndicator); - // + + // Save the pair to avoid their forced intersection + BOPDS_MapOfPaveBlock* pMPB = myFPBDone.ChangeSeek(nF); + if (!pMPB) + pMPB = myFPBDone.Bound(nF, BOPDS_MapOfPaveBlock()); + pMPB->Add(aPB); }//for (; aIt.More(); aIt.Next()) { }//for (; myIterator->More(); myIterator->Next()) { // @@ -656,3 +667,351 @@ void BOPAlgo_PaveFiller::ReduceIntersectionRange(const Standard_Integer theV1, } } } + +//======================================================================= +//function : ForceInterfEF +//purpose : +//======================================================================= +void BOPAlgo_PaveFiller::ForceInterfEF() +{ + if (!myIsPrimary) + return; + + // Now that we have vertices increased and unified, try to find additional + // edge/face common blocks among the pairs of edge/face. + // Here, we are interested in common blocks only, as all real intersections + // should have happened already. Thus, we need to check only those pairs + // of edge/face which have the same vertices. + + // Collect all pave blocks + BOPDS_IndexedMapOfPaveBlock aMPB; + const Standard_Integer aNbS = myDS->NbSourceShapes(); + for (Standard_Integer nE = 0; nE < aNbS; ++nE) + { + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nE); + if (aSI.ShapeType() != TopAbs_EDGE) + // Not an edge + continue; + + if (!aSI.HasReference()) + // Edge has no pave blocks + continue; + + if (aSI.HasFlag()) + // Degenerated edge + continue; + + const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(nE); + BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB); + for (; aItLPB.More(); aItLPB.Next()) + { + const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value(); + const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB); + aMPB.Add(aPBR); + } + } + + // Perform intersection of collected pave blocks with faces + ForceInterfEF(aMPB, Standard_True); +} + +//======================================================================= +//function : ForceInterfEF +//purpose : +//======================================================================= +void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB, + const Standard_Boolean theAddInterf) +{ + if (theMPB.IsEmpty()) + return; + + // Fill the tree with bounding boxes of the pave blocks + NCollection_UBTree aBBTree; + NCollection_UBTreeFiller aTreeFiller(aBBTree); + + Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; + BOPDS_IndexedMapOfPaveBlock aPBMap(1, anAlloc); + + Standard_Integer aNbPB = theMPB.Extent(); + for (Standard_Integer iPB = 1; iPB <= aNbPB; ++iPB) + { + Handle(BOPDS_PaveBlock) aPB = theMPB(iPB); + if (!aPB->HasShrunkData() || !myDS->IsValidShrunkData(aPB)) + { + FillShrunkData(aPB); + if (!aPB->HasShrunkData()) + continue; + } + + Standard_Real f, l; + Bnd_Box aPBBox; + Standard_Boolean isSplit; + aPB->ShrunkData(f, l, aPBBox, isSplit); + + aTreeFiller.Add(aPBMap.Add(aPB), aPBBox); + } + + // Shake the tree + aTreeFiller.Fill(); + + const Standard_Boolean bSICheckMode = (myArguments.Extent() == 1); + + // Find pairs of Face/PaveBlock containing the same vertices + // and prepare those pairs for intersection. + BOPAlgo_VectorOfEdgeFace aVEdgeFace; + + const Standard_Integer aNbS = myDS->NbSourceShapes(); + for (Standard_Integer nF = 0; nF < aNbS; ++nF) + { + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF); + if (aSI.ShapeType() != TopAbs_FACE) + // Not a face + continue; + + if (!aSI.HasReference()) + // Face has no face info + continue; + + const Bnd_Box& aBoxF = aSI.Box(); + BOPCol_BoxBndTreeSelector aSelector; + aSelector.SetBox(aBoxF); + + if (!aBBTree.Select(aSelector)) + continue; + + const TopoDS_Face& aF = TopoDS::Face(aSI.Shape()); + const BOPDS_FaceInfo& aFI = myDS->FaceInfo(nF); + // Vertices of the face + BOPCol_MapOfInteger aMVF; + const BOPCol_MapOfInteger* pMVF[] = { &aFI.VerticesOn(), + &aFI.VerticesIn(), + &aFI.VerticesSc() }; + for (Standard_Integer iM = 0; iM < 3; ++iM) + { + BOPCol_MapIteratorOfMapOfInteger itM(*pMVF[iM]); + for (; itM.More(); itM.Next()) + aMVF.Add(itM.Value()); + } + + // Pave Blocks of the face + const BOPDS_IndexedMapOfPaveBlock* pMPBF[] = { &aFI.PaveBlocksOn(), + &aFI.PaveBlocksIn(), + &aFI.PaveBlocksSc() }; + for (Standard_Integer iM = 0; iM < 3; ++iM) + { + const Standard_Integer aNb = pMPBF[iM]->Extent(); + for (Standard_Integer iPB = 1; iPB <= aNb; ++iPB) + { + const Handle(BOPDS_PaveBlock)& aPB = pMPBF[iM]->FindKey(iPB); + aMVF.Add(aPB->Pave1().Index()); + aMVF.Add(aPB->Pave2().Index()); + } + } + + // Projection tool + GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF); + BRepAdaptor_Surface& aSurfAdaptor = myContext->SurfaceAdaptor (aF); + + // Iterate on pave blocks and combine pairs containing + // the same vertices + const BOPCol_ListOfInteger& aLIPB = aSelector.Indices(); + BOPCol_ListOfInteger::Iterator itLIPB(aLIPB); + for (; itLIPB.More(); itLIPB.Next()) + { + const Handle(BOPDS_PaveBlock)& aPB = aPBMap(itLIPB.Value()); + if (pMPBF[0]->Contains(aPB) || + pMPBF[1]->Contains(aPB) || + pMPBF[2]->Contains(aPB)) + continue; + + // Check if the face contains both vertices of the pave block + Standard_Integer nV1, nV2; + aPB->Indices(nV1, nV2); + if (!aMVF.Contains(nV1) || !aMVF.Contains(nV2)) + // Face does not contain the vertices + continue; + + // Get the edge + Standard_Integer nE; + if (!aPB->HasEdge(nE)) + { + nE = aPB->OriginalEdge(); + if (nE < 0) + continue; + + // Make sure that the edge and face came from different arguments + if (myDS->Rank(nF) == myDS->Rank(nE)) + continue; + } + + const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE)); + BRepAdaptor_Curve aBAC(aE); + + // Check directions coincidence at middle point on the edge + // and projection of that point on the face. + // If the angle between tangent vector to the curve and normal + // of the face is not in the range of 65 - 115 degrees, do not use the additional + // tolerance, as it may lead to undesired unification of edge with the face. + Standard_Boolean bUseAddTol = Standard_True; + + Standard_Real aTS[2]; + Bnd_Box aPBBox; + Standard_Boolean isSplit; + aPB->ShrunkData(aTS[0], aTS[1], aPBBox, isSplit); + + // Middle point + gp_Pnt aPOnE; + // Tangent vector in the middle point + gp_Vec aVETgt; + aBAC.D1(BOPTools_AlgoTools2D::IntermediatePoint(aTS[0], aTS[1]), aPOnE, aVETgt); + if (aVETgt.SquareMagnitude() < gp::Resolution()) + continue; + + aProjPS.Perform(aPOnE); + if (!aProjPS.NbPoints()) + continue; + + // Check the distance in the middle point, using the max vertices + // tolerance as the criteria. + const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1)); + const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2)); + + // In the Self-Interference check mode we are interested in real + // intersections only, so use only the real tolerance of edges, + // no need to use the extended tolerance. + Standard_Real aTolCheck = (bSICheckMode ? myFuzzyValue : + 2 * Max(BRep_Tool::Tolerance(aV1), BRep_Tool::Tolerance(aV2))); + + if (aProjPS.LowerDistance() > aTolCheck + myFuzzyValue) + continue; + + Standard_Real U, V; + aProjPS.LowerDistanceParameters(U, V); + if (!myContext->IsPointInFace(aF, gp_Pnt2d(U, V))) + continue; + + if (aSurfAdaptor.GetType() != GeomAbs_Plane || + aBAC.GetType() != GeomAbs_Line) + { + gp_Pnt aPOnS = aProjPS.NearestPoint(); + gp_Vec aVFNorm(aPOnS, aPOnE); + if (aVFNorm.SquareMagnitude() > gp::Resolution()) + { + // Angle between vectors should be close to 90 degrees. + // We allow deviation of 10 degrees. + Standard_Real aCos = aVFNorm.Normalized().Dot (aVETgt.Normalized()); + if (Abs(aCos) > 0.17365) + bUseAddTol = Standard_False; + } + } + + // Compute an addition to Fuzzy value + Standard_Real aTolAdd = 0.0; + if (bUseAddTol) + { + // Compute the distance from the bounding points of the edge + // to the face and use the maximal of these distances as a + // fuzzy tolerance for the intersection. + // Use the maximal tolerance of the pave block's vertices + // as a max criteria for the computed distance. + + for (Standard_Integer iP = 0; iP < 2; ++iP) + { + gp_Pnt aP = aBAC.Value(aTS[iP]); + aProjPS.Perform(aP); + if (aProjPS.NbPoints()) + { + Standard_Real aDistEF = aProjPS.LowerDistance(); + if (aDistEF < aTolCheck && aDistEF > aTolAdd) + aTolAdd = aDistEF; + } + } + if (aTolAdd > 0.) + { + aTolAdd -= (BRep_Tool::Tolerance(aE) + BRep_Tool::Tolerance(aF)); + if (aTolAdd < 0.) + aTolAdd = 0.; + } + } + + Standard_Boolean bIntersect = aTolAdd > 0; + if (!bIntersect) + { + const BOPDS_MapOfPaveBlock* pMPB = myFPBDone.Seek(nF); + bIntersect = !pMPB || !(pMPB->Contains(aPB)); + } + + if (bIntersect) + { + // Prepare pair for intersection + BOPAlgo_EdgeFace& aEdgeFace = aVEdgeFace.Append1(); + aEdgeFace.SetIndices(nE, nF); + aEdgeFace.SetPaveBlock(aPB); + aEdgeFace.SetEdge(aE); + aEdgeFace.SetFace(aF); + //aEdgeFace.SetBoxes (myDS->ShapeInfo(nE).Box(), myDS->ShapeInfo (nF).Box()); + aEdgeFace.SetFuzzyValue(myFuzzyValue + aTolAdd); + aEdgeFace.UseQuickCoincidenceCheck(Standard_True); + aEdgeFace.SetRange(IntTools_Range(aPB->Pave1().Parameter(), aPB->Pave2().Parameter())); + aEdgeFace.SetProgressIndicator(myProgressIndicator); + } + } + } + + Standard_Integer aNbEFs = aVEdgeFace.Length(); + if (!aNbEFs) + return; + + aPBMap.Clear(); + anAlloc->Reset(); + + // Perform intersection of the found pairs + BOPAlgo_EdgeFaceCnt::Perform (myRunParallel, aVEdgeFace, myContext); + + BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF(); + if (theAddInterf && aEFs.IsEmpty()) + aEFs.SetIncrement(10); + + // Analyze the results of intersection looking for TopAbs_EDGE + // intersection type only. + + // Collect all pairs for common block creation + BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(1, anAlloc); + + for (Standard_Integer i = 0; i < aNbEFs; ++i) + { + BOPAlgo_EdgeFace& anEdgeFace = aVEdgeFace(i); + if (!anEdgeFace.IsDone() || anEdgeFace.HasErrors()) + continue; + + const IntTools_SequenceOfCommonPrts& aCParts = anEdgeFace.CommonParts(); + if (aCParts.Length() != 1) + continue; + + const IntTools_CommonPrt& aCP = aCParts(1); + if (aCP.Type() != TopAbs_EDGE) + continue; + + Standard_Integer nE, nF; + anEdgeFace.Indices(nE, nF); + if (theAddInterf) + { + // Add interference + BOPDS_InterfEF& aEF = aEFs.Append1(); + aEF.SetIndices(nE, nF); + aEF.SetCommonPart(aCP); + myDS->AddInterf(nE, nF); + } + + const Handle(BOPDS_PaveBlock)& aPB = anEdgeFace.PaveBlock(); + // Update face information with new IN pave block + myDS->ChangeFaceInfo(nF).ChangePaveBlocksIn().Add(aPB); + if (theAddInterf) + // Fill map for common blocks creation + BOPAlgo_Tools::FillMap(aPB, nF, aMPBLI, anAlloc); + } + + if (aMPBLI.Extent()) + // Create new common blocks for coinciding pairs + BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, anAlloc, myDS); +} diff --git a/src/BOPAlgo/BOPAlgo_Tools.cxx b/src/BOPAlgo/BOPAlgo_Tools.cxx index d91da1432b..3458362d05 100644 --- a/src/BOPAlgo/BOPAlgo_Tools.cxx +++ b/src/BOPAlgo/BOPAlgo_Tools.cxx @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -38,6 +39,8 @@ #include #include +#include + #include #include @@ -64,10 +67,13 @@ #include #include +#include #include #include +#include + typedef NCollection_IndexedDataMap BOPAlgo_IndexedDataMapOfShapeDir; typedef NCollection_IndexedDataMap @@ -1088,3 +1094,537 @@ void BOPAlgo_Tools::IntersectVertices(const BOPCol_IndexedDataMapOfShapeReal& th } } } +//======================================================================= +// Classification of the faces relatively solids +//======================================================================= + +//======================================================================= +//class : BOPAlgo_ShapeBox +//purpose : Auxiliary class defining ShapeBox structure +//======================================================================= +class BOPAlgo_ShapeBox +{ +public: + //! Empty constructor + BOPAlgo_ShapeBox() {}; + //! Sets the shape + void SetShape(const TopoDS_Shape& theS) + { + myShape = theS; + }; + //! Returns the shape + const TopoDS_Shape& Shape() const + { + return myShape; + }; + //! Sets the bounding box + void SetBox(const Bnd_Box& theBox) + { + myBox = theBox; + }; + //! Returns the bounding box + const Bnd_Box& Box() const + { + return myBox; + }; +private: + TopoDS_Shape myShape; + Bnd_Box myBox; +}; +// Vector of ShapeBox +typedef BOPCol_NCVector BOPAlgo_VectorOfShapeBox; + +//======================================================================= +//class : BOPAlgo_FillIn3DParts +//purpose : Auxiliary class for faces classification in parallel mode +//======================================================================= +class BOPAlgo_FillIn3DParts : public BOPAlgo_Algo +{ +public: + DEFINE_STANDARD_ALLOC + + //! Constructor + BOPAlgo_FillIn3DParts() + { + myBBTree = NULL; + myVShapeBox = NULL; + }; + + //! Destructor + virtual ~BOPAlgo_FillIn3DParts() {}; + + //! Sets the solid + void SetSolid(const TopoDS_Solid& theSolid) + { + mySolid = theSolid; + }; + + //! Returns the solid + const TopoDS_Solid& Solid() const + { + return mySolid; + }; + + //! Sets the box for the solid + void SetBoxS(const Bnd_Box& theBox) + { + myBoxS = theBox; + }; + + //! Returns the solid's box + const Bnd_Box& BoxS() const + { + return myBoxS; + }; + + //! Sets own INTERNAL faces of the solid + void SetOwnIF(const BOPCol_ListOfShape& theLIF) + { + myOwnIF = theLIF; + }; + + //! Returns own INTERNAL faces of the solid + const BOPCol_ListOfShape& OwnIF() const + { + return myOwnIF; + }; + + //! Sets the Bounding Box tree + void SetBBTree(const BOPCol_BoxBndTree& theBBTree) + { + myBBTree = (BOPCol_BoxBndTree*)&theBBTree; + }; + + //! Sets the ShapeBox structure + void SetShapeBoxVector(const BOPAlgo_VectorOfShapeBox& theShapeBox) + { + myVShapeBox = (BOPAlgo_VectorOfShapeBox*)&theShapeBox; + }; + + //! Sets the context + void SetContext(const Handle(IntTools_Context)& theContext) + { + myContext = theContext; + } + + //! Returns the context + const Handle(IntTools_Context)& Context() const + { + return myContext; + } + + //! Performs the classification + virtual void Perform(); + + //! Returns the faces classified as IN for solid + const BOPCol_ListOfShape& InFaces() const + { + return myInFaces; + }; + +private: + + //! Prepares Edge-Face connection map of the given shape + void MapEdgesAndFaces(const TopoDS_Shape& theF, + BOPCol_IndexedDataMapOfShapeListOfShape& theEFMap, + const Handle(NCollection_BaseAllocator)& theAlloc); + + //! Makes the connexity block of faces using the connection map + void MakeConnexityBlock(const TopoDS_Face& theF, + const BOPCol_IndexedMapOfShape& theMEToAvoid, + const BOPCol_IndexedDataMapOfShapeListOfShape& theEFMap, + BOPCol_MapOfShape& theMFDone, + BOPCol_ListOfShape& theLCB, + TopoDS_Face& theFaceToClassify); + + TopoDS_Solid mySolid; //! Solid + Bnd_Box myBoxS; // Bounding box of the solid + BOPCol_ListOfShape myOwnIF; //! Own INTERNAL faces of the solid + BOPCol_ListOfShape myInFaces; //! Faces classified as IN + + BOPCol_BoxBndTree* myBBTree; //! UB tree of bounding boxes + BOPAlgo_VectorOfShapeBox* myVShapeBox; //! ShapeBoxMap + + TopoDS_Iterator myItF; //! Iterators + TopoDS_Iterator myItW; + + Handle(IntTools_Context) myContext; //! Context +}; + +//======================================================================= +//function : BOPAlgo_FillIn3DParts::Perform +//purpose : +//======================================================================= +void BOPAlgo_FillIn3DParts::Perform() +{ + BOPAlgo_Algo::UserBreak(); + + myInFaces.Clear(); + + // 1. Select boxes of faces that are not out of aBoxS + BOPCol_BoxBndTreeSelector aSelector; + aSelector.SetBox(myBoxS); + // + if (!myBBTree->Select(aSelector)) + return; + + const BOPCol_ListOfInteger& aLIFP = aSelector.Indices(); + + // 2. Fill maps of edges and faces of the solid + + Handle(NCollection_BaseAllocator) anAlloc = new NCollection_IncAllocator; + + BOPAlgo_VectorOfShapeBox& aVShapeBox = *myVShapeBox; + + BOPCol_IndexedMapOfShape aMSE(1, anAlloc), aMSF(1, anAlloc); + BOPTools::MapShapes(mySolid, TopAbs_EDGE, aMSE); + BOPTools::MapShapes(mySolid, TopAbs_FACE, aMSF); + + // Check if the Solid contains any faces + Standard_Boolean bIsEmpty = aMSF.IsEmpty(); + + // Add own internal faces of the solid into aMSF + BOPCol_ListIteratorOfListOfShape aItLS(myOwnIF); + for (; aItLS.More(); aItLS.Next()) + aMSF.Add(aItLS.Value()); + + // 3. aIVec - faces to process. + // Filter the selected faces with faces of the solid. + BOPCol_NCVector aIVec(256, anAlloc); + + BOPCol_ListIteratorOfListOfInteger aItLI(aLIFP); + for (; aItLI.More(); aItLI.Next()) { + Standard_Integer nFP = aItLI.Value(); + const TopoDS_Shape& aFP = aVShapeBox(nFP).Shape(); + if (!aMSF.Contains(aFP)) + aIVec.Append1() = nFP; + } + + // 4. Classify faces relatively solid. + // Store faces that are IN mySolid into + + Standard_Integer k, aNbFP = aIVec.Length(); + // Sort indices if necessary + if (aNbFP > 1) + std::sort(aIVec.begin(), aIVec.end()); + + if (bIsEmpty) + { + // The solid is empty as it does not contain any faces. + // It could happen when the input solid consists of INTERNAL faces only. + // Classification of any point relatively empty solid would always give IN status. + // Thus, we consider all selected faces as IN without real classification. + for (k = 0; k < aNbFP; ++k) + myInFaces.Append(aVShapeBox(aIVec(k)).Shape()); + + return; + } + + // Prepare EF map of faces to process for building connexity blocks + BOPCol_IndexedDataMapOfShapeListOfShape aMEFP(1, anAlloc); + if (aNbFP > 1) + { + for (k = 0; k < aNbFP; ++k) + MapEdgesAndFaces(aVShapeBox(aIVec(k)).Shape(), aMEFP, anAlloc); + } + + // Map of Edge-Face connection, necessary for solid classification. + // It will be filled when first classification is performed. + BOPCol_IndexedDataMapOfShapeListOfShape aMEFDS(1, anAlloc); + + // Fence map to avoid processing of the same faces twice + BOPCol_MapOfShape aMFDone(1, anAlloc); + + for (k = 0; k < aNbFP; ++k) + { + Standard_Integer nFP = aIVec(k); + const TopoDS_Face& aFP = (*(TopoDS_Face*)&aVShapeBox(nFP).Shape()); + if (!aMFDone.Add(aFP)) + continue; + + // Make connexity blocks of faces, avoiding passing through the + // borders of the solid. It helps to reduce significantly the + // number of classified faces. + BOPCol_ListOfShape aLCBF(anAlloc); + // The most appropriate face for classification + TopoDS_Face aFaceToClassify; + MakeConnexityBlock(aFP, aMSE, aMEFP, aMFDone, aLCBF, aFaceToClassify); + + if (!myBoxS.IsWhole()) + { + // First, try fast classification of the whole block by additional + // check on bounding boxes - check that bounding boxes of all vertices + // of the block interfere with the box of the solid. + // If not, the faces are out. + Standard_Boolean bOut = Standard_False; + aItLS.Initialize(aLCBF); + for (; aItLS.More() && !bOut; aItLS.Next()) + { + TopExp_Explorer anExpV(aItLS.Value(), TopAbs_VERTEX); + for (; anExpV.More() && !bOut; anExpV.Next()) + { + const TopoDS_Vertex& aV = TopoDS::Vertex(anExpV.Current()); + Bnd_Box aBBV; + aBBV.Add(BRep_Tool::Pnt(aV)); + aBBV.SetGap(BRep_Tool::Tolerance(aV)); + bOut = myBoxS.IsOut(aBBV); + } + } + if (bOut) + continue; + } + + if (aFaceToClassify.IsNull()) + aFaceToClassify = aFP; + + if (aMEFDS.IsEmpty()) + // Fill EF map for Solid + BOPTools::MapShapesAndAncestors(mySolid, TopAbs_EDGE, TopAbs_FACE, aMEFDS); + + // All vertices are interfere with the solids box, run classification. + Standard_Boolean bIsIN = BOPTools_AlgoTools::IsInternalFace + (aFaceToClassify, mySolid, aMEFDS, Precision::Confusion(), myContext); + if (bIsIN) + { + aItLS.Initialize(aLCBF); + for (; aItLS.More(); aItLS.Next()) + myInFaces.Append(aItLS.Value()); + } + } +} +//======================================================================= +// function: MapEdgesAndFaces +// purpose: +//======================================================================= +void BOPAlgo_FillIn3DParts::MapEdgesAndFaces(const TopoDS_Shape& theF, + BOPCol_IndexedDataMapOfShapeListOfShape& theEFMap, + const Handle(NCollection_BaseAllocator)& theAllocator) +{ + myItF.Initialize(theF); + for (; myItF.More(); myItF.Next()) + { + const TopoDS_Shape& aW = myItF.Value(); + if (aW.ShapeType() != TopAbs_WIRE) + continue; + + myItW.Initialize(aW); + for (; myItW.More(); myItW.Next()) + { + const TopoDS_Shape& aE = myItW.Value(); + + BOPCol_ListOfShape* pLF = theEFMap.ChangeSeek(aE); + if (!pLF) + pLF = &theEFMap(theEFMap.Add(aE, BOPCol_ListOfShape(theAllocator))); + pLF->Append(theF); + } + } +} +//======================================================================= +// function: MakeConnexityBlock +// purpose: +//======================================================================= +void BOPAlgo_FillIn3DParts::MakeConnexityBlock(const TopoDS_Face& theFStart, + const BOPCol_IndexedMapOfShape& theMEAvoid, + const BOPCol_IndexedDataMapOfShapeListOfShape& theEFMap, + BOPCol_MapOfShape& theMFDone, + BOPCol_ListOfShape& theLCB, + TopoDS_Face& theFaceToClassify) +{ + // Add start element + theLCB.Append(theFStart); + if (theEFMap.IsEmpty()) + return; + + BOPCol_ListIteratorOfListOfShape aItCB(theLCB); + for (; aItCB.More(); aItCB.Next()) + { + const TopoDS_Shape& aF = aItCB.Value(); + myItF.Initialize(aF); + for (; myItF.More(); myItF.Next()) + { + const TopoDS_Shape& aW = myItF.Value(); + if (aW.ShapeType() != TopAbs_WIRE) + continue; + + myItW.Initialize(aW); + for (; myItW.More(); myItW.Next()) + { + const TopoDS_Shape& aE = myItW.Value(); + if (theMEAvoid.Contains(aE)) + { + if (theFaceToClassify.IsNull()) + theFaceToClassify = TopoDS::Face(aF); + continue; + } + + const BOPCol_ListOfShape* pLF = theEFMap.Seek(aE); + if (!pLF) + continue; + BOPCol_ListIteratorOfListOfShape aItLF(*pLF); + for (; aItLF.More(); aItLF.Next()) + { + const TopoDS_Shape& aFToAdd = aItLF.Value(); + if (theMFDone.Add(aFToAdd)) + theLCB.Append(aFToAdd); + } + } + } + } +} + +// Vector of solid classifiers +typedef BOPCol_NCVector BOPAlgo_VectorOfFillIn3DParts; + +// Functors to perform classification +typedef BOPCol_ContextFunctor BOPAlgo_FillIn3DPartsFunctor; + +typedef BOPCol_ContextCnt BOPAlgo_FillIn3DPartsCnt; + +namespace { + static void buildBoxForSolid (const TopoDS_Solid& theSolid, + Bnd_Box& theBox) + { + Standard_Boolean bIsOpenBox = Standard_False; + for (TopoDS_Iterator itS (theSolid); itS.More() && !bIsOpenBox; itS.Next()) + { + const TopoDS_Shell& aShell = TopoDS::Shell (itS.Value()); + bIsOpenBox = BOPTools_AlgoTools::IsOpenShell (aShell); + + if (bIsOpenBox) + break; + + for (TopoDS_Iterator itF (aShell); itF.More(); itF.Next()) + { + const TopoDS_Face& aF = TopoDS::Face (itF.Value()); + + Bnd_Box aBoxF; + BRepBndLib::Add (aF, aBoxF); + + bIsOpenBox = (aBoxF.IsOpenXmin() || aBoxF.IsOpenXmax() || + aBoxF.IsOpenYmin() || aBoxF.IsOpenYmax() || + aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax()); + + if (bIsOpenBox) + break; + + theBox.Add (aBoxF); + } + } + if (bIsOpenBox || BOPTools_AlgoTools::IsInvertedSolid (theSolid)) + theBox.SetWhole(); + } +} + +//======================================================================= +//function : ClassifyFaces +//purpose : +//======================================================================= +void BOPAlgo_Tools::ClassifyFaces(const BOPCol_ListOfShape& theFaces, + const BOPCol_ListOfShape& theSolids, + const Standard_Boolean theRunParallel, + Handle(IntTools_Context)& theContext, + BOPCol_IndexedDataMapOfShapeListOfShape& theInParts, + const BOPCol_IndexedDataMapOfShapeBox* theBoxes, + const BOPCol_DataMapOfShapeListOfShape* theSolidsIF) +{ + Handle(NCollection_BaseAllocator) anAlloc = new NCollection_IncAllocator; + + // Fill the vector of shape box with faces and its bounding boxes + BOPAlgo_VectorOfShapeBox aVSB(256, anAlloc); + + BOPCol_ListIteratorOfListOfShape aItLF(theFaces); + for (; aItLF.More(); aItLF.Next()) + { + const TopoDS_Shape& aF = aItLF.Value(); + // Append face to the vector of shape box + BOPAlgo_ShapeBox& aSB = aVSB.Append1(); + aSB.SetShape(aF); + + Bnd_Box aBox; + if (theBoxes) + { + const Bnd_Box* pBox = theBoxes->Seek (aF); + if (pBox) + aBox = *pBox; + } + + if (aBox.IsVoid()) + { + // Build the bounding box + BRepBndLib::Add(aF, aBox); + } + aSB.SetBox(aBox); + } + + // Prepare UB tree of bounding boxes of the faces to classify + // taking the bounding boxes from the just prepared vector + BOPCol_BoxBndTree aBBTree; + NCollection_UBTreeFiller aTreeFiller(aBBTree); + + Standard_Integer aNbF = aVSB.Length(); + for (Standard_Integer i = 0; i < aNbF; ++i) + { + aTreeFiller.Add(i, aVSB(i).Box()); + } + + // Shake tree filler + aTreeFiller.Fill(); + + // Prepare vector of solids to classify + BOPAlgo_VectorOfFillIn3DParts aVFIP; + + BOPCol_ListIteratorOfListOfShape aItLS(theSolids); + for (; aItLS.More(); aItLS.Next()) + { + const TopoDS_Solid& aSolid = TopoDS::Solid(aItLS.Value()); + + // Build the bounding box for the solid + Bnd_Box aBox; + if (theBoxes) + { + const Bnd_Box* pBox = theBoxes->Seek (aSolid); + if (pBox) + aBox = *pBox; + } + if (aBox.IsVoid()) + { + buildBoxForSolid (aSolid, aBox); + } + + // Append solid to the vector + BOPAlgo_FillIn3DParts& aFIP = aVFIP.Append1(); + aFIP.SetSolid(aSolid); + aFIP.SetBoxS(aBox); + + if (theSolidsIF) + { + const BOPCol_ListOfShape* pLIF = theSolidsIF->Seek(aSolid); + if (pLIF) + aFIP.SetOwnIF(*pLIF); + } + + aFIP.SetBBTree(aBBTree); + aFIP.SetShapeBoxVector(aVSB); + } + + // Perform classification + //================================================================ + BOPAlgo_FillIn3DPartsCnt::Perform(theRunParallel, aVFIP, theContext); + //================================================================ + + // Analyze the results and fill the resulting map + + Standard_Integer aNbS = aVFIP.Length(); + for (Standard_Integer i = 0; i < aNbS; ++i) + { + BOPAlgo_FillIn3DParts& aFIP = aVFIP(i); + const TopoDS_Shape& aS = aFIP.Solid(); + const BOPCol_ListOfShape& aLFIn = aFIP.InFaces(); + theInParts.Add(aS, aLFIn); + } +} diff --git a/src/BOPAlgo/BOPAlgo_Tools.hxx b/src/BOPAlgo/BOPAlgo_Tools.hxx index a43ab1f008..35696c193a 100644 --- a/src/BOPAlgo/BOPAlgo_Tools.hxx +++ b/src/BOPAlgo/BOPAlgo_Tools.hxx @@ -21,6 +21,9 @@ #include #include +#include +#include +#include #include #include #include @@ -155,6 +158,27 @@ public: const Standard_Real theFuzzyValue, BOPCol_ListOfListOfShape& theChains); + //! Classifies the faces relatively solids . + //! The IN faces for solids are stored into output data map . + //! + //! The map contains INTERNAL faces of the solids, to avoid + //! their additional classification. + //! + //! Firstly, it checks the intersection of bounding boxes of the shapes. + //! If the Box is not stored in the map, it builds the box. + //! If the bounding boxes of solid and face are interfering the classification is performed. + //! + //! It is assumed that all faces and solids are already intersected and + //! do not have any geometrically coinciding parts without topological + //! sharing of these parts + Standard_EXPORT static void ClassifyFaces(const BOPCol_ListOfShape& theFaces, + const BOPCol_ListOfShape& theSolids, + const Standard_Boolean theRunParallel, + Handle(IntTools_Context)& theContext, + BOPCol_IndexedDataMapOfShapeListOfShape& theInParts, + const BOPCol_IndexedDataMapOfShapeBox* theBoxes = 0, + const BOPCol_DataMapOfShapeListOfShape* theSolidsIF = 0); + }; #endif // _BOPAlgo_Tools_HeaderFile diff --git a/tests/boolean/bcut_complex/F2 b/tests/boolean/bcut_complex/F2 index 5ca5836f25..14c45f93e5 100644 --- a/tests/boolean/bcut_complex/F2 +++ b/tests/boolean/bcut_complex/F2 @@ -1,12 +1,31 @@ # Original bug : buc60127 # Date : 18mar98 -puts "TODO #22911 ALL: Faulty shapes in variables faulty_1 to faulty_" -puts "TODO #22911 ALL: Error : The area of result shape is" - restore [locate_data_file buc60127-part.rle] part restore [locate_data_file buc60127-tool.rle] tool +# fix the part shape + +explode part f +# fix inner cylinder +mksurface c_in part_1 +trim c_in c_in +mkface f_in c_in 0 2*pi 0 150 + +# fix side faces +mksurface s1 part_3 +mksurface s2 part_4 +mkface f1 s1 -10 10 -10 10 +mkface f2 s2 -10 10 -10 10 + +# fix solid +mkvolume r part_2 f_in f1 f2 +explode r so +copy r_1 part + bcut result part tool -checkprops result -s 0 -checkview -display result -2d -s -otherwise { part tool } -path ${imagedir}/${test_image}.png +checkshape result +checkprops result -s 5382.41 -v 2643.38 +checknbshapes result -wire 14 -face 11 -shell 1 -solid 1 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/boolean/bfuse_complex/F5 b/tests/boolean/bfuse_complex/F5 index 192bb9641c..06a59bfbb5 100644 --- a/tests/boolean/bfuse_complex/F5 +++ b/tests/boolean/bfuse_complex/F5 @@ -6,5 +6,8 @@ restore [locate_data_file pro10658b.rle] b bfuse result a b -checkprops result -s 8636.79 -checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png \ No newline at end of file +checkshape result +checkprops result -s 8231.06 -v 30472.5 +checknbshapes result -wire 9 -face 9 -shell 1 -solid 1 + +checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/boolean/bfuse_complex/Q2 b/tests/boolean/bfuse_complex/Q2 index 4667b47a78..8e7387c05a 100644 --- a/tests/boolean/bfuse_complex/Q2 +++ b/tests/boolean/bfuse_complex/Q2 @@ -1,9 +1,11 @@ # pro10658 -puts "TODO ALL: Error : The area of result shape is" restore [locate_data_file CTO900_pro10658a.rle] a restore [locate_data_file pro10658b.rle] b bfuse result a b -checkprops result -s 8231.06 -checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png \ No newline at end of file +checkshape result +checkprops result -s 8231.06 -v 30472.5 +checknbshapes result -wire 9 -face 9 -shell 1 -solid 1 + +checkview -display result -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/boolean/bopfuse_complex/H1 b/tests/boolean/bopfuse_complex/H1 index a2acc294c7..c9948f4e46 100644 --- a/tests/boolean/bopfuse_complex/H1 +++ b/tests/boolean/bopfuse_complex/H1 @@ -1,11 +1,16 @@ -puts "TODO #22911 ALL: Error : The area of result shape is" -puts "TODO OCC25735 ALL: Faulty shapes in variables faulty_1 to" - restore [locate_data_file a102] a restore [locate_data_file b136] b +# fix the second shape +fixshape b b +# revert the tolerance +settolerance b 0.003 + bop a b bopfuse result -checkprops result -s 0 -checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png +checkshape result +checknbshapes result -vertex 16 -edge 28 -wire 13 -face 13 -shell 1 -solid 1 +checkprops result -s 20777.6 -v 173396 + +checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/boolean/bsection/R8 b/tests/boolean/bsection/R8 index 8ea1ae823f..eb3dd899c0 100644 --- a/tests/boolean/bsection/R8 +++ b/tests/boolean/bsection/R8 @@ -8,6 +8,6 @@ restore [locate_data_file ger61235b.brep] object bsection result object tool -checkprops result -l 11.8242 +checkprops result -l 16.4762 checksection result checkview -display result -2d -otherwise { object tool } -l -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_6/bug26619 b/tests/bugs/modalg_6/bug26619 index be7baec534..202475552c 100644 --- a/tests/bugs/modalg_6/bug26619 +++ b/tests/bugs/modalg_6/bug26619 @@ -1,5 +1,3 @@ -puts "TODO OCC27014 ALL: Error : result is WRONG because number of .* entities in shape" - puts "============" puts "OCC26619" puts "============" @@ -22,21 +20,9 @@ bnondestructive 1 bop h0 f0 bopsection result -checkprops result -l 142.264 +checkprops result -l 150.232 -set nbshapes_expected " -Number of shapes in shape - VERTEX : 46 - EDGE : 46 - WIRE : 0 - FACE : 0 - SHELL : 0 - SOLID : 0 - COMPSOLID : 0 - COMPOUND : 1 - SHAPE : 93 -" -checknbshapes result -ref ${nbshapes_expected} -t -m "result" +checknbshapes result -vertex 45 -edge 45 -t -m "result" regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance h0] full MaxTolerance2 @@ -46,3 +32,7 @@ set tol_rel_MaxTolerance 0.0001 checkreal "MaxTolerance" ${MaxTolerance2} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance} checkview -display result -2d -path ${imagedir}/${test_image}.png + +if {[regexp "alone_1" [checksection result]]} { + puts "Error: the section is not closed" +} \ No newline at end of file diff --git a/tests/bugs/modalg_6/bug26789_1 b/tests/bugs/modalg_6/bug26789_1 index c5dddec066..c1bb6f2b38 100644 --- a/tests/bugs/modalg_6/bug26789_1 +++ b/tests/bugs/modalg_6/bug26789_1 @@ -1,8 +1,6 @@ puts "TODO 0026789 ALL: Error : The area of result shape is" puts "TODO 0026789 ALL: Error : The volume of result shape is" -puts "TODO 0026789 ALL: Error : is WRONG because number of SOLID entities in shape" -puts "TODO 0026789 ALL: Error : is WRONG because number of SHELL entities in shape" -puts "TODO 0026789 ALL: Faulty shapes in variables faulty_" +puts "TODO 0026789 ALL: Error : is WRONG because number of" puts "========" puts "OCC26789" diff --git a/tests/bugs/modalg_7/bug25983_1 b/tests/bugs/modalg_7/bug25983_1 new file mode 100644 index 0000000000..9d5204f1a7 --- /dev/null +++ b/tests/bugs/modalg_7/bug25983_1 @@ -0,0 +1,30 @@ +puts "TODO OCC25983 ALL: Error : is WRONG because number of" +puts "TODO OCC25983 ALL: Error : The area of result shape is" +puts "TODO OCC25983 ALL: Error : The volume of result shape is" + +puts "========" +puts "OCC25983" +puts "========" +puts "" +########################################## +# Fusion of sweep and its mirror invalid +########################################## + +restore [locate_data_file bug25983_deform-fusion1-tcl-BSpline.brep] BSpline +wire Knurling-0-spine BSpline +mksweep Knurling-0-spine +setsweep -FR +polyline DWire 0 0 0 1 -0.9999999999999998 0 1.0000000000000002 0.9999999999999998 0 0 0 0 +trotate DWire 0 0 0 1 0 0 134.99999999999693 +ttranslate DWire 9 0 0 +addsweep DWire +buildsweep Knurling -C -S +copy Knurling Clone +tmirror Clone 0 0 0 1 0 0 +bfuse result Knurling Clone + +checkshape result +checknbshapes result -wire 24 -face 24 -shell 1 -solid 1 +checkprops result -s 262.476 -v 54.0383 + +checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_7/bug25983 b/tests/bugs/modalg_7/bug25983_2 similarity index 77% rename from tests/bugs/modalg_7/bug25983 rename to tests/bugs/modalg_7/bug25983_2 index 9eb515cdb2..23fad7968d 100644 --- a/tests/bugs/modalg_7/bug25983 +++ b/tests/bugs/modalg_7/bug25983_2 @@ -1,5 +1,3 @@ -puts "TODO OCC25983 ALL: Faulty shapes in variables faulty_1 to faulty_" - puts "========" puts "OCC25983" puts "========" @@ -19,6 +17,12 @@ addsweep DWire buildsweep Knurling -C -S copy Knurling Clone tmirror Clone 0 0 0 1 0 0 + +bfuzzyvalue 1.e-3 bfuse result Knurling Clone checkshape result +checknbshapes result -wire 24 -face 24 -shell 1 -solid 1 +checkprops result -s 262.476 -v 54.0383 + +checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_7/bug27049 b/tests/bugs/modalg_7/bug27049 index e5ea7d0077..7f77aba424 100644 --- a/tests/bugs/modalg_7/bug27049 +++ b/tests/bugs/modalg_7/bug27049 @@ -23,7 +23,7 @@ tolerance f0 bop h0 f0 bopsection result -checkprops result -l 142.264 +checkprops result -l 150.23 set nbshapes_expected " Number of shapes in shape diff --git a/tests/bugs/modalg_7/bug31662 b/tests/bugs/modalg_7/bug31662 new file mode 100644 index 0000000000..82cfa10e3e --- /dev/null +++ b/tests/bugs/modalg_7/bug31662 @@ -0,0 +1,32 @@ +puts "=============================================================================================" +puts "0031662: Modeling Algorithms - Incomplete result of section operation" +puts "=============================================================================================" +puts "" + +restore [locate_data_file bug31662_Surface_0.brep] s0 +restore [locate_data_file bug31662_Surface_1.brep] s1 + +bclearobjects +bcleartools +baddobjects s0 +baddtools s1 +bfillds + +bbop r4 4 + +checkshape r4 +checksection r4 -r 0 +checkprops r4 -l 70.3856 + +bbuild rgf + +checkshape rgf +checknbshapes rgf -wire 363 -face 363 -shell 2 -solid 0 + +mkvolume result rgf -ni + +checkshape result +checknbshapes result -wire 254 -face 254 -shell 1 -solid 1 +checkprops result -s 668.352 -v 774.749 + +checkview -display result -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/moddata_1/bug152_2 b/tests/bugs/moddata_1/bug152_2 index cecc8a21bb..7d852f20f8 100755 --- a/tests/bugs/moddata_1/bug152_2 +++ b/tests/bugs/moddata_1/bug152_2 @@ -1,4 +1,4 @@ -puts "TODO OCC22033 ALL: Faulty shapes in variables faulty_1 to faulty_" +#puts "TODO OCC22033 ALL: Faulty shapes in variables faulty_1 to faulty_" if { [regexp {Debug mode} [dversion]] } { puts "TODO OCC22033 ALL: TEST INCOMPLETE" puts "TODO OCC22033 ALL: Exception" diff --git a/tests/bugs/moddata_2/bug26_2 b/tests/bugs/moddata_2/bug26_2 index 0eaa5d7ffa..7d655ac768 100755 --- a/tests/bugs/moddata_2/bug26_2 +++ b/tests/bugs/moddata_2/bug26_2 @@ -1,5 +1,3 @@ -puts "TODO CR25432 ALL: Error : The area of result shape is" - puts "================" puts "OCC26" puts "================" @@ -12,5 +10,6 @@ checkshape a_2 bfuse result a_2 a_1 -checkprops result -s 41539.9 +checkprops result -s 41539.9 -v 348665 +checknbshapes result -wire 44 -face 41 -shell 1 -solid 1 checkview -display result -2d -path ${imagedir}/${test_image}.png