1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-08 14:17:06 +03:00

0030559: BOP Fuse: result is inconsistent

Implement alternative approach for making the edge seam (closed) on the face. This approach is useful for non-periodic surfaces (e.g. tore-like surface of revolution is periodic in U direction only).
Avoid internal faces in the affected solids of the result of BOP Fuse.
This commit is contained in:
emv
2020-09-16 15:05:50 +03:00
committed by bugmaster
parent b3bf8485a2
commit d476fc37f8
9 changed files with 158 additions and 30 deletions

View File

@@ -39,6 +39,7 @@
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Surface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
@@ -72,8 +73,8 @@ static
//function : DoSplitSEAMOnFace
//purpose :
//=======================================================================
void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
const TopoDS_Face& aF)
Standard_Boolean BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
const TopoDS_Face& aF)
{
Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft;
Standard_Real aTol, a, b, anUPeriod, anVPeriod, aT, anU, dU, anU1;
@@ -131,7 +132,7 @@ void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
bIsVPeriodic=aSB->IsVPeriodic();
//
if (!(bIsUPeriodic || bIsVPeriodic)) {
return;
return Standard_False;
}
anUPeriod = bIsUPeriodic ? aSB->UPeriod() : 0.;
anVPeriod = bIsVPeriodic ? aSB->VPeriod() : 0.;
@@ -139,7 +140,7 @@ void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
//
if (aRTS.IsNull()) {
if (!bIsUClosed && !bIsVClosed) {
return;
return Standard_False;
}
//
if (bIsUClosed) {
@@ -191,7 +192,7 @@ void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
}
//
if (anU1==anU && anV1==anV) {
return;
return Standard_False;
}
//
aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY;
@@ -222,7 +223,96 @@ void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
}
}
return Standard_True;
}
//=======================================================================
//function : DoSplitSEAMOnFace
//purpose :
//=======================================================================
Standard_Boolean BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& theEOrigin,
const TopoDS_Edge& theESplit,
const TopoDS_Face& theFace)
{
if (!BRep_Tool::IsClosed (theEOrigin, theFace))
return Standard_False;
if (BRep_Tool::IsClosed (theESplit, theFace))
return Standard_True;
TopoDS_Edge aESplit = theESplit;
aESplit.Orientation (TopAbs_FORWARD);
TopoDS_Face aFace = theFace;
aFace.Orientation (TopAbs_FORWARD);
Standard_Real aTS1, aTS2;
Handle(Geom2d_Curve) aC2DSplit = BRep_Tool::CurveOnSurface (aESplit, aFace, aTS1, aTS2);
if (aC2DSplit.IsNull())
return Standard_False;
Standard_Real aT1, aT2;
Handle(Geom2d_Curve) aC2D1 = BRep_Tool::CurveOnSurface (
TopoDS::Edge (theEOrigin.Oriented (TopAbs_FORWARD)), aFace, aT1, aT2);
Handle(Geom2d_Curve) aC2D2 = BRep_Tool::CurveOnSurface (
TopoDS::Edge (theEOrigin.Oriented (TopAbs_REVERSED)), aFace, aT1, aT2);
Standard_Real aT = BOPTools_AlgoTools2D::IntermediatePoint (aTS1, aTS2);
gp_Pnt2d aPMid;
gp_Vec2d aVTgt;
aC2DSplit->D1 (aT, aPMid, aVTgt);
// project on original 2d curves
Geom2dAPI_ProjectPointOnCurve aProjPC1, aProjPC2;
aProjPC1.Init (aPMid, aC2D1, aT1, aT2);
aProjPC2.Init (aPMid, aC2D2, aT1, aT2);
if (!aProjPC1.NbPoints() && !aProjPC2.NbPoints())
return Standard_False;
Standard_Real aDist1 = aProjPC1.NbPoints() ? aProjPC1.LowerDistance() : RealLast();
Standard_Real aDist2 = aProjPC2.NbPoints() ? aProjPC2.LowerDistance() : RealLast();
if (aDist1 > Precision::PConfusion() && aDist2 > Precision::PConfusion())
return Standard_False;
// choose the closest and take corresponding point from the opposite
gp_Pnt2d aNewPnt = aDist1 < aDist2 ? aC2D2->Value (aProjPC1.LowerDistanceParameter()) :
aC2D1->Value (aProjPC2.LowerDistanceParameter());
Handle (Geom2d_Curve) aTmpC1 = Handle (Geom2d_Curve)::DownCast (aC2DSplit->Copy());
Handle (Geom2d_Curve) aTmpC2 = Handle (Geom2d_Curve)::DownCast (aC2DSplit->Copy());
Handle (Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve (aTmpC1, aTS1, aTS2);
Handle (Geom2d_TrimmedCurve) aC2 = new Geom2d_TrimmedCurve (aTmpC2, aTS1, aTS2);
gp_Vec2d aTrVec (aPMid, aNewPnt);
aC2->Translate (aTrVec);
gp_Pnt2d aPProj;
gp_Vec2d aVTgtOrigin;
if (aDist1 < aDist2)
{
aC2D1->D1 (aProjPC1.LowerDistanceParameter(), aPProj, aVTgtOrigin);
}
else
{
aC2D2->D1 (aProjPC2.LowerDistanceParameter(), aPProj, aVTgtOrigin);
}
Standard_Real aDot = aVTgt.Dot (aVTgtOrigin);
if ((aDist1 < aDist2) == (aDot > 0))
{
BRep_Builder().UpdateEdge (aESplit, aC1, aC2, aFace, BRep_Tool::Tolerance (aESplit));
}
else
{
BRep_Builder().UpdateEdge (aESplit, aC2, aC1, aFace, BRep_Tool::Tolerance (aESplit));
}
return Standard_True;
}
//=======================================================================
//function : GetNormalToFaceOnEdge
//purpose :

View File

@@ -43,11 +43,15 @@ public:
DEFINE_STANDARD_ALLOC
//! Makes the edge <theESplit> seam edge for the face <theFace> basing on the surface properties (U and V periods)
Standard_EXPORT static Standard_Boolean DoSplitSEAMOnFace (const TopoDS_Edge& theESplit,
const TopoDS_Face& theFace);
//! Make the edge <aSp> seam edge for the face <aF>
Standard_EXPORT static void DoSplitSEAMOnFace (const TopoDS_Edge& aSp,
const TopoDS_Face& aF);
//! Makes the split edge <theESplit> seam edge for the face <theFace> basing on the positions
//! of 2d curves of the original edge <theEOrigin>.
Standard_EXPORT static Standard_Boolean DoSplitSEAMOnFace (const TopoDS_Edge& theEOrigin,
const TopoDS_Edge& theESplit,
const TopoDS_Face& theFace);
//! Computes normal to the face <aF> for the point on the edge <aE>
//! at parameter <aT>.<br>