Boolean Operations algorithm has been improved to handle the cases with empty shapes arguments correctly.
Test cases for the issue.
// or equal to the MAXIMAL dimension of the TOOLS;
// 4. COMMON: The arguments and tools could have any dimensions.
//
- Standard_Integer iDimMin[2], iDimMax[2];
+ Standard_Integer iDimMin[2] = { 0, 0 }, iDimMax[2] = { 0, 0 };
Standard_Boolean bHasValid[2] = {Standard_False, Standard_False};
//
for (i=0; i<2; ++i) {
AddError (new BOPAlgo_AlertBOPNotAllowed);
return;
}
- myDims[0] = iDimMin[0];
- myDims[1] = iDimMin[1];
+ }
+
+ if (bHasValid[0] || bHasValid[1])
+ {
+ // In case of all empty shapes in one of the groups
+ // this group aquires the dimension of other group
+ myDims[0] = bHasValid[0] ? iDimMin[0] : iDimMin[1];
+ myDims[1] = bHasValid[1] ? iDimMin[1] : iDimMin[0];
}
}
//=======================================================================
// One of the groups of arguments consists of empty shapes only,
// so we can build the result of operation right away just by
// choosing the list of shapes to add to result, depending on
- // the type of the operation
+ // the type of the operation.
+ // Although, if the group with valid shapes consists from more
+ // than just one shape, depending on the operation type we may need
+ // to split the shapes in this group before adding them into result.
+
TopTools_ListOfShape *pLResult = NULL;
//
switch (myOperation) {
case BOPAlgo_FUSE:
+ {
+ if (aLValidObjs.Extent() + aLValidTools.Extent() > 1)
+ // The arguments must be split before adding into result
+ return Standard_False;
+
// Add not empty shapes into result
pLResult = bHasValidObj ? &aLValidObjs : &aLValidTools;
break;
+ }
case BOPAlgo_CUT:
+ {
+ if (aLValidObjs.Extent() > 1)
+ // The objects must be split before adding into result
+ return Standard_False;
+
// Add objects into result
pLResult = &aLValidObjs;
break;
+ }
case BOPAlgo_CUT21:
+ {
+ if (aLValidTools.Extent() > 1)
+ // The tools must be split before adding into result
+ return Standard_False;
+
// Add tools into result
pLResult = &aLValidTools;
break;
+ }
case BOPAlgo_COMMON:
- // Common will be empty
+ // Common will always be empty
break;
default:
break;
{
Standard_Boolean bDone = TreatEmptyShape();
if (bDone) {
+ PrepareHistory();
return;
}
}
}
//! History Tool
- Handle(BRepTools_History) History() const
+ Handle(BRepTools_History) History()
{
- return myFillHistory ? myHistory : NULL;
+ if (myFillHistory)
+ {
+ if (myHistory.IsNull())
+ // It seems the algorithm has exited with error before filling
+ // the history. Initialize the History tool to return the empty
+ // History instead of NULL.
+ myHistory = new BRepTools_History();
+
+ return myHistory;
+ }
+
+ // If the History has not been requested to be filled, return the NULL
+ // explicitly as the History may be partially filled for the algorithm's
+ // internal needs.
+ return NULL;
}
public: //! @name Enabling/Disabling the history collection.
//==============================================================================
void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
{
- Merge(*theHistory23.get());
+ if (!theHistory23.IsNull())
+ Merge(*theHistory23.get());
}
//==============================================================================
//function : Merge
//==============================================================================
void BRepTools_History::Merge(const BRepTools_History& theHistory23)
{
+ if (!(theHistory23.HasModified() ||
+ theHistory23.HasGenerated() ||
+ theHistory23.HasRemoved()))
+ // nothing to merge
+ return;
+
// Propagate R23 directly and M23 and G23 fully to M12 and G12.
// Remember the propagated shapes.
TopTools_DataMapOfShapeListOfShape* aS1ToGAndM[] =
TopTools_IndexedMapOfShape anArgsMap;
TopTools_ListIteratorOfListOfShape aIt(theArguments);
for (; aIt.More(); aIt.Next())
- TopExp::MapShapes(aIt.Value(), anArgsMap);
+ {
+ if (!aIt.Value().IsNull())
+ TopExp::MapShapes(aIt.Value(), anArgsMap);
+ }
// Copy the history for all supported shapes from the algorithm
Standard_Integer i, aNb = anArgsMap.Extent();
--- /dev/null
+puts "========"
+puts "OCC29973: Modeling Algorithms - access violation within BRepAlgoAPI_Cut on empty input shape"
+puts "========"
+puts ""
+
+
+pload QAcommands
+
+compound c
+box b 1 2 3
+if {![regexp "Test complete" [OCC25446 r b c 2]]} {
+ puts "Error: test incomplete"
+}
+
+compound b bc
+checknbshapes r -ref [nbshapes bc]
+checkprops r -equal bc
--- /dev/null
+puts "========"
+puts "OCC29973: Modeling Algorithms - access violation within BRepAlgoAPI_Cut on empty input shape"
+puts "========"
+puts ""
+
+
+box b1 10 10 10
+box b2 5 5 5 10 10 10
+compound c
+
+bclearobjects
+bcleartools
+baddobjects b1 b2
+baddtools c
+bfillds
+bbop r_0 0
+bbop r_1 1
+bbop r_2 2
+bbop r_3 3
+bbop r_4 4
+
+checkshape r_0
+checknbshapes r_0 -shape 1
+checkprops r_0 -s empty -v empty
+
+checkshape r_1
+checknbshapes r_1 -wire 12 -face 12 -solid 1 -shell 1
+checkprops r_1 -s 1050 -v 1875
+
+checkshape r_2
+checknbshapes r_2 -wire 18 -face 18 -solid 3 -shell 3
+checkprops r_2 -s 1350 -v 1875
+
+checkshape r_3
+checknbshapes r_3 -shape 1
+checkprops r_3 -s empty -v empty
+
+checkshape r_4
+checknbshapes r_4 -vertex 6 -edge 6
+checkprops r_4 -l 30
+
+# reverse the arguments
+
+bclearobjects
+bcleartools
+baddobjects c
+baddtools b1 b2
+bfillds
+bbop r1_0 0
+bbop r1_1 1
+bbop r1_2 2
+bbop r1_3 3
+bbop r1_4 4
+
+checkshape r1_0
+checknbshapes r1_0 -ref [nbshapes r_0]
+checkprops r1_0 -equal r_0
+
+checkshape r1_1
+checknbshapes r1_1 -ref [nbshapes r_1]
+checkprops r1_1 -equal r_1
+
+checkshape r1_2
+checknbshapes r1_2 -ref [nbshapes r_3]
+checkprops r1_2 -equal r_3
+
+checkshape r1_3
+checknbshapes r1_3 -ref [nbshapes r_2]
+checkprops r1_3 -equal r_2
+
+checkshape r1_4
+checknbshapes r1_4 -ref [nbshapes r_4]
+checkprops r1_4 -equal r_4