X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_BooleanDriver.cxx;h=abfc738eaa38435dfec6a0ef047022f51eaf918d;hb=2736f682fe0d63fbaf9dff49c46b4fa6c23d72ce;hp=32b0b04fa21b02af7d5861013d0b7f0e8a5dadd5;hpb=ef95b8ac70d50ab64058ffcc124ef9f2cf7ba9cc;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx index 32b0b04fa..abfc738ea 100644 --- a/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_BooleanDriver.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -31,18 +31,14 @@ #include -#include -#include - #include -#include #include #include #include #include -#include #include #include +#include #include #include @@ -73,33 +69,23 @@ static TopoDS_Shape RemoveExtraEdges(const TopoDS_Shape &theShape) { TopoDS_Shape aResult; - if (theShape.IsNull() == Standard_False) { + if (!theShape.IsNull()) { BlockFix_BlockFixAPI aTool; aTool.OptimumNbFaces() = 0; aTool.SetShape(theShape); aTool.Perform(); - aResult = aTool.Shape(); - - // Repair result - BRepCheck_Analyzer anAna (aResult, false); - Standard_Boolean isValid = anAna.IsValid(); + TopoDS_Shape aShape = aTool.Shape(); - if (!isValid) { + if (GEOMUtils::CheckShape(aShape)) { + aResult = aShape; + } + else { TopoDS_Shape aFixed; ShHealOper_ShapeProcess aHealer; - - aHealer.Perform(aResult, aFixed); - - if (aHealer.isDone()) { + aHealer.Perform(aShape, aFixed); + if (aHealer.isDone() && GEOMUtils::CheckShape(aFixed)) aResult = aFixed; - anAna.Init(aResult, false); - isValid = anAna.IsValid(); - } - } - - if (!isValid) { - aResult.Nullify(); } } @@ -128,7 +114,7 @@ GEOMImpl_BooleanDriver::GEOMImpl_BooleanDriver() //function : Execute //purpose : //======================================================================= -Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const +Standard_Integer GEOMImpl_BooleanDriver::Execute(Handle(TFunction_Logbook)& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); @@ -153,11 +139,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (!aShape1.IsNull() && !aShape2.IsNull()) { // check arguments for Mantis issue 0021019 - BRepCheck_Analyzer ana (aShape1, Standard_True); - if (!ana.IsValid()) - StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - ana.Init(aShape2); - if (!ana.IsValid()) + if (!GEOMUtils::CheckShape(aShape1, true) || !GEOMUtils::CheckShape(aShape2, true)) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); if (isCheckSelfInte) { @@ -168,11 +150,11 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const aList2.Append(aShape2); aCSI.SetArguments(aList1); aCSI.Perform(); - if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) + if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); aCSI.SetArguments(aList2); aCSI.Perform(); - if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) + if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); } @@ -209,12 +191,11 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (nbShapes > 0) { aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(1)); aShape = aRefShape->GetValue(); - + if (!aShape.IsNull()) { - BRepCheck_Analyzer anAna (aShape, Standard_True); - if (!anAna.IsValid()) { + // check arguments for Mantis issue 0021019 + if (!GEOMUtils::CheckShape(aShape, true)) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - } BOPAlgo_CheckerSI aCSI; // checker of self-interferences @@ -224,7 +205,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const aList1.Append(aShape); aCSI.SetArguments(aList1); aCSI.Perform(); - if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) { StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); } } @@ -237,20 +218,18 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const aShape = aShapeCopy; for (i = 2; i <= nbShapes; i++) { - aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(i)); - aShape2 = aRefShape->GetValue(); - anAna.Init(aShape2); - - if (!anAna.IsValid()) { - StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - } - + aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(i)); + aShape2 = aRefShape->GetValue(); + + if (!GEOMUtils::CheckShape(aShape2, true)) + StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); + if (isCheckSelfInte) { BOPCol_ListOfShape aList2; aList2.Append(aShape2); aCSI.SetArguments(aList2); aCSI.Perform(); - if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) { StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); } } @@ -258,17 +237,17 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const // Copy shape aShapeCopy.Nullify(); TNaming_CopyShape::CopyTool(aShape2, aMapTShapes, aShapeCopy); - aShape = performOperation (aShape, aShapeCopy, aSimpleType); + aShape = performOperation (aShape, aShapeCopy, aSimpleType); if (isRmExtraEdges) { aShape = RemoveExtraEdges(aShape); } - - if (aShape.IsNull()) { - return 0; - } - } - } + + if (aShape.IsNull()) { + return 0; + } + } + } } } break; @@ -280,13 +259,10 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const if (!aShape.IsNull()) { // check arguments for Mantis issue 0021019 - BRepCheck_Analyzer anAna (aShape, Standard_True); - - if (!anAna.IsValid()) { + if (!GEOMUtils::CheckShape(aShape, true)) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - } - BOPAlgo_CheckerSI aCSI; // checker of self-interferences + BOPAlgo_CheckerSI aCSI; // checker of self-interferences if (isCheckSelfInte) { aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL); @@ -294,7 +270,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const aList1.Append(aShape); aCSI.SetArguments(aList1); aCSI.Perform(); - if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) { StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); } } @@ -305,7 +281,7 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const TNaming_CopyShape::CopyTool(aShape, aMapTShapes, aShapeCopy); aShape = aShapeCopy; - + Handle(TColStd_HSequenceOfTransient) aTools = aCI.GetShapes(); const Standard_Integer nbShapes = aTools->Length(); Standard_Integer i; @@ -315,18 +291,16 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const for (i = 1; i <= nbShapes; i++) { aRefTool = Handle(GEOM_Function)::DownCast(aTools->Value(i)); aTool = aRefTool->GetValue(); - anAna.Init(aTool); - if (!anAna.IsValid()) { + if (!GEOMUtils::CheckShape(aTool, true)) StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid"); - } if (isCheckSelfInte) { BOPCol_ListOfShape aList2; aList2.Append(aTool); aCSI.SetArguments(aList2); aCSI.Perform(); - if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) { + if (aCSI.HasErrors() || aCSI.DS().Interferences().Extent() > 0) { StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected"); } } @@ -349,11 +323,67 @@ Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const aFunction->SetValue(aShape); - log.SetTouched(Label()); + log->SetTouched(Label()); return 1; } +//======================================================================= +//function : makeCompoundShellFromFaces +//purpose : +//======================================================================= +TopoDS_Shape GEOMImpl_BooleanDriver::makeCompoundShellFromFaces + (const TopoDS_Shape theShape)const +{ + if (theShape.ShapeType() != TopAbs_COMPOUND) + return theShape; + + BRep_Builder B; + TopoDS_Compound aFaces; + B.MakeCompound(aFaces); + + // simplify compound structure for + // Mantis issue 0023419 (note 0021712) + TopExp_Explorer aExp; + TopTools_MapOfShape aMapFaces; + aExp.Init(theShape, TopAbs_FACE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shape& aFace = aExp.Current(); + if (aMapFaces.Add(aFace)) { + B.Add(aFaces, aFace); + } + } + + BOPCol_ListOfShape aListShapes; + BOPTools_AlgoTools::MakeConnexityBlocks(aFaces, TopAbs_EDGE, TopAbs_FACE, aListShapes); + + if (aListShapes.IsEmpty()) + return theShape; + + TopoDS_Compound aResult; + B.MakeCompound(aResult); + BOPCol_ListIteratorOfListOfShape anIter(aListShapes); + + for (; anIter.More(); anIter.Next()) { + TopoDS_Shell aShell; + B.MakeShell(aShell); + TopoDS_Shape aShapeFromFaces = anIter.Value(); + aExp.Init(aShapeFromFaces, TopAbs_FACE); + for (; aExp.More(); aExp.Next()) { + const TopoDS_Shape& aFace = aExp.Current(); + B.Add(aShell, aFace); + } + if (!aShell.IsNull()) { + BOPTools_AlgoTools::OrientFacesOnShell(aShell); + B.Add(aResult, aShell); + } + else + B.Add(aResult, aShapeFromFaces); + } + + return aResult; +} + //======================================================================= //function : performOperation //purpose : @@ -392,10 +422,14 @@ TopoDS_Shape GEOMImpl_BooleanDriver::performOperation TopoDS_Shape aStepResult = BO.Shape(); // check result of this step: if it is a compound (boolean operations - // allways return a compound), we add all sub-shapes of it. + // always return a compound), we add all sub-shapes of it. // This allows to avoid adding empty compounds, // resulting from COMMON on two non-intersecting shapes. if (aStepResult.ShapeType() == TopAbs_COMPOUND) { + if ((aValue1.ShapeType() == TopAbs_FACE || aValue1.ShapeType() == TopAbs_SHELL) && + (aValue2.ShapeType() == TopAbs_FACE || aValue2.ShapeType() == TopAbs_SHELL)) { + aStepResult = makeCompoundShellFromFaces(aStepResult); + } TopoDS_Iterator aCompIter (aStepResult); for (; aCompIter.More(); aCompIter.Next()) { // add shape in a result @@ -449,10 +483,14 @@ TopoDS_Shape GEOMImpl_BooleanDriver::performOperation } if (isCompound) { // check result of this step: if it is a compound (boolean operations - // allways return a compound), we add all sub-shapes of it. + // always return a compound), we add all sub-shapes of it. // This allows to avoid adding empty compounds, // resulting from CUT of parts if (aCut.ShapeType() == TopAbs_COMPOUND) { + if (itSub1.Value().ShapeType() == TopAbs_FACE || + itSub1.Value().ShapeType() == TopAbs_SHELL) { + aCut = makeCompoundShellFromFaces(aCut); + } TopoDS_Iterator aCompIter (aCut); for (; aCompIter.More(); aCompIter.Next()) { // add shape in a result @@ -480,12 +518,32 @@ TopoDS_Shape GEOMImpl_BooleanDriver::performOperation // perform FUSE operation else if (theType == BOOLEAN_FUSE) { + Standard_Boolean isFaces = Standard_False; + TopTools_ListOfShape listShape1, listShape2; + GEOMUtils::AddSimpleShapes(theShape1, listShape1); + GEOMUtils::AddSimpleShapes(theShape2, listShape2); + + TopTools_ListIteratorOfListOfShape itSub1 (listShape1); + for (; itSub1.More(); itSub1.Next()) { + TopoDS_Shape aValue1 = itSub1.Value(); + TopTools_ListIteratorOfListOfShape itSub2 (listShape2); + for (; itSub2.More(); itSub2.Next()) { + TopoDS_Shape aValue2 = itSub2.Value(); + if ((aValue1.ShapeType() == TopAbs_FACE || aValue1.ShapeType() == TopAbs_SHELL) && + (aValue2.ShapeType() == TopAbs_FACE || aValue2.ShapeType() == TopAbs_SHELL)) { + isFaces = Standard_True; + } + } + } + // Perform BRepAlgoAPI_Fuse BO (theShape1, theShape2); if (!BO.IsDone()) { StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes"); } aShape = BO.Shape(); + if (isFaces) + aShape = makeCompoundShellFromFaces(aShape); } // perform SECTION operation @@ -517,7 +575,7 @@ TopoDS_Shape GEOMImpl_BooleanDriver::performOperation BO.ComputePCurveOn1(Standard_True); BO.ComputePCurveOn2(Standard_True); //modified by NIZNHY-PKV Tue Oct 18 14:34:18 2011t - + BO.Build(); if (!BO.IsDone()) { StdFail_NotDone::Raise("Section operation can not be performed on the given shapes"); @@ -526,7 +584,7 @@ TopoDS_Shape GEOMImpl_BooleanDriver::performOperation TopoDS_Shape aStepResult = BO.Shape(); // check result of this step: if it is a compound (boolean operations - // allways return a compound), we add all sub-shapes of it. + // always return a compound), we add all sub-shapes of it. // This allows to avoid adding empty compounds, // resulting from SECTION on two non-intersecting shapes. if (aStepResult.ShapeType() == TopAbs_COMPOUND) { @@ -572,91 +630,8 @@ TopoDS_Shape GEOMImpl_BooleanDriver::performOperation } // 08.07.2008 skl for bug 19761 from Mantis - BRepCheck_Analyzer ana (aShape, Standard_True); - ana.Init(aShape); - if (!ana.IsValid()) { - ShapeFix_ShapeTolerance aSFT; - aSFT.LimitTolerance(aShape, Precision::Confusion(), - Precision::Confusion(), TopAbs_SHAPE); - Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape); - aSfs->Perform(); - aShape = aSfs->Shape(); - ana.Init(aShape); - if (!ana.IsValid()) - Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result"); - } - - // BEGIN: Mantis issue 0021060: always limit tolerance of BOP result - // 1. Get shape parameters for comparison - int nbTypes [TopAbs_SHAPE]; - { - for (int iType = 0; iType < TopAbs_SHAPE; ++iType) - nbTypes[iType] = 0; - nbTypes[aShape.ShapeType()]++; - - TopTools_MapOfShape aMapOfShape; - aMapOfShape.Add(aShape); - TopTools_ListOfShape aListOfShape; - aListOfShape.Append(aShape); - - TopTools_ListIteratorOfListOfShape itL (aListOfShape); - for (; itL.More(); itL.Next()) { - TopoDS_Iterator it (itL.Value()); - for (; it.More(); it.Next()) { - TopoDS_Shape s = it.Value(); - if (aMapOfShape.Add(s)) { - aListOfShape.Append(s); - nbTypes[s.ShapeType()]++; - } - } - } - } - - // 2. Limit tolerance - TopoDS_Shape aShapeCopy; - TColStd_IndexedDataMapOfTransientTransient aMapTShapes; - TNaming_CopyShape::CopyTool(aShape, aMapTShapes, aShapeCopy); - ShapeFix_ShapeTolerance aSFT; - aSFT.LimitTolerance(aShapeCopy, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE); - Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShapeCopy); - aSfs->Perform(); - aShapeCopy = aSfs->Shape(); - - // 3. Check parameters - ana.Init(aShapeCopy); - if (ana.IsValid()) { - int iType, nbTypesCopy [TopAbs_SHAPE]; - - for (iType = 0; iType < TopAbs_SHAPE; ++iType) - nbTypesCopy[iType] = 0; - nbTypesCopy[aShapeCopy.ShapeType()]++; - - TopTools_MapOfShape aMapOfShape; - aMapOfShape.Add(aShapeCopy); - TopTools_ListOfShape aListOfShape; - aListOfShape.Append(aShapeCopy); - - TopTools_ListIteratorOfListOfShape itL (aListOfShape); - for (; itL.More(); itL.Next()) { - TopoDS_Iterator it (itL.Value()); - for (; it.More(); it.Next()) { - TopoDS_Shape s = it.Value(); - if (aMapOfShape.Add(s)) { - aListOfShape.Append(s); - nbTypesCopy[s.ShapeType()]++; - } - } - } - - bool isEqual = true; - for (iType = 0; iType < TopAbs_SHAPE && isEqual; ++iType) { - if (nbTypes[iType] != nbTypesCopy[iType]) - isEqual = false; - } - if (isEqual) - aShape = aShapeCopy; - } - // END: Mantis issue 0021060 + if ( !GEOMUtils::CheckShape(aShape, true) && !GEOMUtils::FixShapeTolerance(aShape) ) + Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result"); return aShape; } @@ -728,6 +703,4 @@ GetCreationInformation(std::string& theOperationName, return true; } -IMPLEMENT_STANDARD_HANDLE (GEOMImpl_BooleanDriver,GEOM_BaseDriver); - IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_BooleanDriver,GEOM_BaseDriver);