1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

Compare commits

...

1 Commits

Author SHA1 Message Date
emv
8e196cf90c 0028474: Boolean operations - General Fuse operator breaks validity of resulting shape
1. Re-orienting the shell before making solid from it (MakeShell in BOPAlgo_ShellSplitter);

2. The implementation of the BOPTools_AlgoTools::IsSplitToReverse() method has been changed to
   make the usage of the Hatcher for looking for the point in the face default.

3. Test cases for the issue.
2017-04-13 11:30:33 +03:00
4 changed files with 104 additions and 71 deletions

View File

@@ -661,6 +661,8 @@ void MakeShell(const BOPCol_ListOfShape& aLS,
const TopoDS_Shape& aF=aIt.Value();
aBB.Add(aShell, aF);
}
//
BOPTools_AlgoTools::OrientFacesOnShell(aShell);
}
//=======================================================================
// function: MapEdgesAndFaces

View File

@@ -1087,93 +1087,80 @@ Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
const TopoDS_Face& theFSr,
Handle(IntTools_Context)& theContext)
{
Standard_Boolean bRet, bFound, bInFace;
Standard_Real aT1, aT2, aT, aU, aV, aScPr;
gp_Pnt aPFSp, aPFSr;
gp_Dir aDNFSp;
gp_Vec aD1U, aD1V;
Handle(Geom_Surface) aSr, aSp;
TopAbs_Orientation aOrSr, aOrSp;
TopExp_Explorer anExp;
TopoDS_Edge aESp;
//
bRet=Standard_False;
//
aSr=BRep_Tool::Surface(theFSr);
aSp=BRep_Tool::Surface(theFSp);
if (aSr==aSp) {
aOrSr=theFSr.Orientation();
aOrSp=theFSp.Orientation();
bRet=(aOrSr!=aOrSp);
return bRet;
// Compare surfaces
Handle(Geom_Surface) aSFSp = BRep_Tool::Surface(theFSp);
Handle(Geom_Surface) aSFOr = BRep_Tool::Surface(theFSr);
if (aSFSp == aSFOr) {
return theFSp.Orientation() != theFSr.Orientation();
}
//
bFound=Standard_False;
anExp.Init(theFSp, TopAbs_EDGE);
for (; anExp.More(); anExp.Next()) {
aESp=(*(TopoDS_Edge*)(&anExp.Current()));
if (!BRep_Tool::Degenerated(aESp)) {
if (!BRep_Tool::IsClosed(aESp, theFSp)) {
bFound=!bFound;
Standard_Boolean bDone = Standard_False;
// Find the point inside the split face
gp_Pnt aPFSp;
gp_Pnt2d aP2DFSp;
//
// Error status
Standard_Integer iErr;
// Use the hatcher to find the point in the middle of the face
iErr = BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
if (iErr) {
// Hatcher has failed to find a point.
// Try to get the point near some not closed and
// not degenerated edge on the split face.
TopExp_Explorer anExp(theFSp, TopAbs_EDGE);
for (; anExp.More(); anExp.Next()) {
const TopoDS_Edge& aESp = (*(TopoDS_Edge*)(&anExp.Current()));
if (!BRep_Tool::Degenerated(aESp) && !BRep_Tool::IsClosed(aESp, theFSp)) {
BOPTools_AlgoTools3D::PointNearEdge
(aESp, theFSp, aP2DFSp, aPFSp, theContext);
break;
}
}
}
if (!bFound) {
Standard_Boolean bFlag;
Standard_Integer iErr;
gp_Pnt2d aP2DFSp;
//
iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp,
theContext);
if (iErr) {
return bRet;
if (!anExp.More()) {
// The point has not been found.
return bDone;
}
//
aP2DFSp.Coord(aU, aV);
bFlag=BOPTools_AlgoTools3D::GetNormalToSurface(aSp, aU, aV, aDNFSp);
if (!bFlag) {
return bRet;
}
//
if (theFSp.Orientation()==TopAbs_REVERSED){
aDNFSp.Reverse();
}
}
else {
BRep_Tool::Range(aESp, aT1, aT2);
aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT,
aPFSp, aDNFSp,
theContext);
}
//
// Parts of theContext->ComputeVS(..)
GeomAPI_ProjectPointOnSurf& aProjector=theContext->ProjPS(theFSr);
// Compute normal direction of the split face
gp_Dir aDNFSp;
bDone = BOPTools_AlgoTools3D::GetNormalToSurface
(aSFSp, aP2DFSp.X(), aP2DFSp.Y(), aDNFSp);
if (!bDone) {
return bDone;
}
//
if (theFSp.Orientation() == TopAbs_REVERSED){
aDNFSp.Reverse();
}
//
// Project the point from the split face on the original face
// to find its UV coordinates
GeomAPI_ProjectPointOnSurf& aProjector = theContext->ProjPS(theFSr);
aProjector.Perform(aPFSp);
if (!aProjector.IsDone()) {
return bRet;
bDone = (aProjector.NbPoints() > 0);
if (!bDone) {
return bDone;
}
//
// UV coordinates of the point on the original face
Standard_Real aU, aV;
aProjector.LowerDistanceParameters(aU, aV);
gp_Pnt2d aP2D(aU, aV);
bInFace=theContext->IsPointInOnFace (theFSr, aP2D);
if (!bInFace) {
return bRet;
//
// Compute normal direction for the original face in this point
gp_Dir aDNFOr;
bDone = BOPTools_AlgoTools3D::GetNormalToSurface(aSFOr, aU, aV, aDNFOr);
if (!bDone) {
return bDone;
}
//
aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
gp_Dir aDD1U(aD1U);
gp_Dir aDD1V(aD1V);
gp_Dir aDNFSr=aDD1U^aDD1V;
if (theFSr.Orientation()==TopAbs_REVERSED){
aDNFSr.Reverse();
if (theFSr.Orientation() == TopAbs_REVERSED) {
aDNFOr.Reverse();
}
//
aScPr=aDNFSp*aDNFSr;
bRet=(aScPr<0.);
//
return bRet;
// compare the normals
Standard_Real aCos = aDNFSp*aDNFOr;
return (aCos < 0.);
}
//=======================================================================
//function :IsSplitToReverse

View File

@@ -0,0 +1,22 @@
puts "========"
puts "OCC28474"
puts "========"
puts ""
#################################################
# Boolean operations - General Fuse operator breaks validity of resulting shape
#################################################
restore [locate_data_file bug28474_shapes1.brep] b
explode b
bclearobjects
bcleartools
baddobjects b_1
baddtools b_2
bfillds
bbuild result
checkshape result
checknbshapes result -shell 2 -solid 2
checkprops result -s 1.37256 -v 0.00204945
checkview -display result -2d -path ${imagedir}/${test_image}.png

View File

@@ -0,0 +1,22 @@
puts "========"
puts "OCC28474"
puts "========"
puts ""
#################################################
# Boolean operations - General Fuse operator breaks validity of resulting shape
#################################################
restore [locate_data_file bug28474_shapes2.brep] b
explode b
bclearobjects
bcleartools
baddobjects b_1
baddtools b_2
bfillds
bbuild result
checkshape result
checknbshapes result -shell 2 -solid 2
checkprops result -s 0.580379 -v 0.000580023
checkview -display result -2d -path ${imagedir}/${test_image}.png