mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
0029698: Regression vs 7.2.0: Common operation raises FLT_INVALID_OPERATION exception
When checking if the split edge is oriented as the original one (BOPTools_AlgoTools::IsSplitToReverse()) the tangent vectors should be computed for both edges at the same point. This point is taken on the split edge and projected on the original edge. The fix is intended to ensuring that the reference point will be taken inside the valid range of the split edge (i.e. not covered by the tolerance spheres of its bounding vertices) and the projection of this point on the original edge will be successful. Moreover, several sampling points are now taken on the split edge and processed until first valid point is found. If requested (by a not null pointer) all *BOPTools_AlgoTools::IsSplitToReverse()* methods are now return the error status of the check. Before using the returned flag, the calling program should check this error status. For successful check the error status should be equal to zero. New warning *BOPAlgo_AlertUnableToOrientTheShape* is now returned in the algorithms in Boolean component in case the check for correct shape orientation failed. Test case for the issue.
This commit is contained in:
@@ -91,3 +91,6 @@ Error: The Feature Removal algorithm 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
|
||||
|
||||
.BOPAlgo_AlertUnableToOrientTheShape
|
||||
Warning: Unable to orient the shape correctly
|
||||
|
@@ -104,4 +104,7 @@ DEFINE_SIMPLE_ALERT(BOPAlgo_AlertRemoveFeaturesFailed)
|
||||
//! and not used for solids creation
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertSolidBuilderUnusedFaces)
|
||||
|
||||
//! Unable to orient the shape correctly
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToOrientTheShape)
|
||||
|
||||
#endif // _BOPAlgo_Alerts_HeaderFile
|
||||
|
@@ -93,4 +93,7 @@ static const char BOPAlgo_BOPAlgo_msg[] =
|
||||
"Error: The Feature Removal algorithm has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertSolidBuilderUnusedFaces\n"
|
||||
"Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation\n";
|
||||
"Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertUnableToOrientTheShape\n"
|
||||
"Warning: Unable to orient the shape correctly\n";
|
||||
|
@@ -58,6 +58,10 @@ class BOPAlgo_PaveFiller;
|
||||
//! i.e. the check is performed. Setting this flag to FALSE for inverted solids,
|
||||
//! most likely will lead to incorrect results.
|
||||
//!
|
||||
//! The algorithm returns the following warnings:
|
||||
//! - *BOPAlgo_AlertUnableToOrientTheShape* - in case the check on the orientation of the split shape
|
||||
//! to match the orientation of the original shape has failed.
|
||||
//!
|
||||
//! The algorithm returns the following Error statuses:
|
||||
//! - *BOPAlgo_AlertTooFewArguments* - in case there are no enough arguments to perform the operation;
|
||||
//! - *BOPAlgo_AlertNoFiller* - in case the intersection tool has not been created;
|
||||
|
@@ -226,7 +226,7 @@ void BOPAlgo_Builder::FillImagesVertices()
|
||||
{
|
||||
TopoDS_Shape aSSIm = aItIm.Value();
|
||||
if (!aSSIm.IsEqual(aSS) &&
|
||||
BOPTools_AlgoTools::IsSplitToReverse(aSSIm, aSS, myContext))
|
||||
BOPTools_AlgoTools::IsSplitToReverseWithWarn(aSSIm, aSS, myContext, myReport))
|
||||
{
|
||||
aSSIm.Reverse();
|
||||
}
|
||||
|
@@ -61,7 +61,8 @@
|
||||
static
|
||||
TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
|
||||
const TopTools_DataMapOfShapeListOfShape& theImages,
|
||||
Handle(IntTools_Context)& theCtx);
|
||||
Handle(IntTools_Context)& theCtx,
|
||||
const Handle(Message_Report)& theReport);
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPAlgo_PairOfShapeBoolean
|
||||
@@ -311,7 +312,7 @@ void BOPAlgo_Builder::BuildSplitFaces()
|
||||
// the draft face will be null, as such sub-shapes may split the face on parts
|
||||
// (as in the case "bugs modalg_5 bug25245_1").
|
||||
// The BuilderFace algorithm will be called in this case.
|
||||
TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext);
|
||||
TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext, myReport);
|
||||
if (!aFD.IsNull())
|
||||
{
|
||||
aFacesIm(aFacesIm.Add(i, TopTools_ListOfShape())).Append(aFD);
|
||||
@@ -404,7 +405,7 @@ void BOPAlgo_Builder::BuildSplitFaces()
|
||||
}// if (bIsClosed){
|
||||
//
|
||||
aSp.Orientation(anOriE);
|
||||
bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
|
||||
bToReverse=BOPTools_AlgoTools::IsSplitToReverseWithWarn(aSp, aE, myContext, myReport);
|
||||
if (bToReverse) {
|
||||
aSp.Reverse();
|
||||
}
|
||||
@@ -813,21 +814,27 @@ void BOPAlgo_Builder::FillInternalVertices()
|
||||
//purpose : Checks if the edge has multi-connected vertices.
|
||||
//=======================================================================
|
||||
static Standard_Boolean HasMultiConnected(const TopoDS_Edge& theEdge,
|
||||
TopTools_DataMapOfShapeInteger& theMap)
|
||||
TopTools_DataMapOfShapeListOfShape& theMap)
|
||||
{
|
||||
TopoDS_Iterator itV(theEdge);
|
||||
for (; itV.More(); itV.Next())
|
||||
{
|
||||
const TopoDS_Shape& aV = itV.Value();
|
||||
Standard_Integer *pCounter = theMap.ChangeSeek(aV);
|
||||
if (!pCounter)
|
||||
pCounter = theMap.Bound(aV, 1);
|
||||
TopTools_ListOfShape *pList = theMap.ChangeSeek(aV);
|
||||
if (!pList)
|
||||
{
|
||||
pList = theMap.Bound(aV, TopTools_ListOfShape());
|
||||
pList->Append(theEdge);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*pCounter == 2)
|
||||
return Standard_True;
|
||||
// The list is expected to be 1-2 elements long,
|
||||
// thus using "Contains" is safe.
|
||||
if (!pList->Contains(theEdge))
|
||||
pList->Append(theEdge);
|
||||
|
||||
++(*pCounter);
|
||||
if (pList->Extent() > 2)
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
return Standard_False;
|
||||
@@ -839,7 +846,8 @@ static Standard_Boolean HasMultiConnected(const TopoDS_Edge& theEdge,
|
||||
//=======================================================================
|
||||
TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
|
||||
const TopTools_DataMapOfShapeListOfShape& theImages,
|
||||
Handle(IntTools_Context)& theCtx)
|
||||
Handle(IntTools_Context)& theCtx,
|
||||
const Handle(Message_Report)& theReport)
|
||||
{
|
||||
BRep_Builder aBB;
|
||||
// Take the information from the original face
|
||||
@@ -855,7 +863,7 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
|
||||
// the vertices appearance, and if the multi-connexity is met return
|
||||
// the null face to use the BuilderFace algorithm for checking the
|
||||
// possibility of split.
|
||||
TopTools_DataMapOfShapeInteger aVerticesCounter;
|
||||
TopTools_DataMapOfShapeListOfShape aVerticesCounter;
|
||||
|
||||
// Update wires of the original face and add them to draft face
|
||||
TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
|
||||
@@ -885,20 +893,21 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
|
||||
return TopoDS_Face();
|
||||
}
|
||||
|
||||
// Check if the original edge is degenerated
|
||||
Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
|
||||
|
||||
// Check for the splits of the edge
|
||||
const TopTools_ListOfShape* pLEIm = theImages.Seek(aE);
|
||||
if (!pLEIm)
|
||||
{
|
||||
// Check if the edge has multi-connected vertices
|
||||
if (HasMultiConnected(aE, aVerticesCounter))
|
||||
if (!bIsDegenerated && HasMultiConnected(aE, aVerticesCounter))
|
||||
return TopoDS_Face();
|
||||
|
||||
aBB.Add(aNewWire, aE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the original edge is degenerated
|
||||
Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
|
||||
// Check if the original edge is closed on the face
|
||||
Standard_Boolean bIsClosed = BRep_Tool::IsClosed(aE, theFace);
|
||||
|
||||
@@ -908,7 +917,7 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
|
||||
TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
|
||||
|
||||
// Check if the split has multi-connected vertices
|
||||
if (HasMultiConnected(aSp, aVerticesCounter))
|
||||
if (!bIsDegenerated && HasMultiConnected(aSp, aVerticesCounter))
|
||||
return TopoDS_Face();
|
||||
|
||||
aSp.Orientation(anOriE);
|
||||
@@ -918,13 +927,13 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check closeness of the split edge and if it is not
|
||||
// make the second PCurve
|
||||
// If the original edge is closed on the face check closeness
|
||||
// of the split edge and if it is not closed make the second PCurve
|
||||
if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
|
||||
BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
|
||||
|
||||
// Check if the split should be reversed
|
||||
if (BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, theCtx))
|
||||
if (BOPTools_AlgoTools::IsSplitToReverseWithWarn(aSp, aE, theCtx, theReport))
|
||||
aSp.Reverse();
|
||||
|
||||
aBB.Add(aNewWire, aSp);
|
||||
|
@@ -287,8 +287,8 @@ void BOPAlgo_Builder::BuildDraftSolid(const TopoDS_Shape& theSolid,
|
||||
theLIF.Append(aFx);
|
||||
}
|
||||
else {
|
||||
bToReverse=BOPTools_AlgoTools::IsSplitToReverse
|
||||
(aFx, aF, myContext);
|
||||
bToReverse=BOPTools_AlgoTools::IsSplitToReverseWithWarn
|
||||
(aFx, aF, myContext, myReport);
|
||||
if (bToReverse) {
|
||||
aFx.Reverse();
|
||||
}
|
||||
|
Reference in New Issue
Block a user