mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-29 14:00:49 +03:00
0029237: Improve performance of Boolean Operations
In order to improve performance of Boolean Operations on the relatively fast cases the following improvements have been made: 1. Initialization of the FaceInfo information for the faces participating in Face/Face interference, even when the gluing is ON, to take into account intersection of their sub-shapes. 2. Code simplification & duplication removal - the methods BOPAlgo_ShellSplitter::MakeConnexityBlocks and BOPAlgo_WireSplitter::MakeConnexityBlocks have been unified into BOPTools_AlgoTools::MakeConnexityBlocks. 3. Avoid unnecessary bounding box computation for solids during DS initialization. The bounding boxes for solids will be computed during the building stage to find faces located inside solids. For the shape self-interference check (performed by the BOPAlgo_CheckerSI), the bounding box is still computed, as it is necessary to resolve Shape/Solid intersections. 4. Use only three sample points to check coincidence of line and plane. 5. Perform necessity of planes intersection only when the gluing is off. 6. Avoid repeated initialization of 2D classifier while building splits of the faces. 7. Post treat stage: 7.1. Method CorrectWires: Save edge's data (PCurve, parameter of the vertex, range) to avoid its recalculation. 7.2. Method CheckEdge: While checking vertices on edges avoid unnecessary calculation of their location. 8. Provide possibility to disable the classification of the input solids on the inverted status (to be the holes in the space). 9. Avoid building of bounding boxes for faces/solids during splitting of the input arguments for their classification relatively hole faces/shells if there are no holes created. 10. Avoid rebuilding of the faces/solids from arguments which does not acquire any inside parts from other arguments during the operation by using their draft versions as their splits. Test cases for the issue. Correction of the test cases boolean gdml_public A9 and bugs modalg_7 bug28485 as they are improvements. Additional test case for the issue #28485 as it is fixed by the current changes.
This commit is contained in:
@@ -113,14 +113,6 @@ static
|
||||
const Standard_Real aTol,
|
||||
const BOPCol_IndexedMapOfShape& aMapToAvoid);
|
||||
|
||||
static
|
||||
Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
|
||||
const TopoDS_Face& theF,
|
||||
const Handle(Geom_Surface)& theS,
|
||||
const TopoDS_Edge& theE1,
|
||||
const TopoDS_Edge& theE2,
|
||||
NCollection_DataMap<TopoDS_Shape, Standard_Real>& theMapEdgeLen);
|
||||
|
||||
//=======================================================================
|
||||
//class : BOPTools_CPC
|
||||
//purpose :
|
||||
@@ -477,55 +469,43 @@ void CheckEdge (const TopoDS_Edge& Ed,
|
||||
const Standard_Real aMaxTol,
|
||||
const BOPCol_IndexedMapOfShape& aMapToAvoid)
|
||||
{
|
||||
Standard_Real aTolE, aTol, aD2, aNewTolerance, dd;
|
||||
gp_Pnt aPC;
|
||||
TopLoc_Location L;
|
||||
TopoDS_Edge aE;
|
||||
TopoDS_Vertex aV;
|
||||
TopoDS_Iterator aItS;
|
||||
//
|
||||
TopAbs_Orientation aOrV;
|
||||
BRep_ListIteratorOfListOfPointRepresentation aItPR;
|
||||
BRep_ListIteratorOfListOfCurveRepresentation aItCR;
|
||||
//
|
||||
aE=Ed;
|
||||
TopoDS_Edge aE = Ed;
|
||||
aE.Orientation(TopAbs_FORWARD);
|
||||
aTolE=BRep_Tool::Tolerance(aE);
|
||||
Standard_Real aTolE = BRep_Tool::Tolerance(aE);
|
||||
//
|
||||
Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
|
||||
//
|
||||
aItS.Initialize(aE);
|
||||
const TopLoc_Location& Eloc = aE.Location();
|
||||
|
||||
TopoDS_Iterator aItS(aE);
|
||||
for (; aItS.More(); aItS.Next()) {
|
||||
aV= TopoDS::Vertex(aItS.Value());
|
||||
const TopoDS_Vertex& aV= TopoDS::Vertex(aItS.Value());
|
||||
//
|
||||
Handle(BRep_TVertex)& TV=*((Handle(BRep_TVertex)*)&aV.TShape());
|
||||
const gp_Pnt& aPV = TV->Pnt();
|
||||
//
|
||||
aTol=BRep_Tool::Tolerance(aV);
|
||||
Standard_Real aTol=BRep_Tool::Tolerance(aV);
|
||||
aTol=Max(aTol, aTolE);
|
||||
dd=0.1*aTol;
|
||||
Standard_Real dd=0.1*aTol;
|
||||
aTol*=aTol;
|
||||
//
|
||||
const TopLoc_Location& Eloc = aE.Location();
|
||||
//
|
||||
aItCR.Initialize(TE->Curves());
|
||||
BRep_ListIteratorOfListOfCurveRepresentation aItCR(TE->Curves());
|
||||
while (aItCR.More()) {
|
||||
const Handle(BRep_CurveRepresentation)& aCR = aItCR.Value();
|
||||
const TopLoc_Location& loc = aCR->Location();
|
||||
L = (Eloc * loc).Predivided(aV.Location());
|
||||
//
|
||||
if (aCR->IsCurve3D()) {
|
||||
const Handle(Geom_Curve)& aC = aCR->Curve3D();
|
||||
if (!aC.IsNull()) {
|
||||
aItPR.Initialize(TV->Points());
|
||||
TopLoc_Location L = (Eloc * aCR->Location()).Predivided(aV.Location());
|
||||
BRep_ListIteratorOfListOfPointRepresentation aItPR(TV->Points());
|
||||
while (aItPR.More()) {
|
||||
const Handle(BRep_PointRepresentation)& aPR=aItPR.Value();
|
||||
if (aPR->IsPointOnCurve(aC, L)) {
|
||||
aPC = aC->Value(aPR->Parameter());
|
||||
gp_Pnt aPC = aC->Value(aPR->Parameter());
|
||||
aPC.Transform(L.Transformation());
|
||||
aD2=aPV.SquareDistance(aPC);
|
||||
Standard_Real aD2=aPV.SquareDistance(aPC);
|
||||
if (aD2 > aTol) {
|
||||
aNewTolerance=sqrt(aD2)+dd;
|
||||
Standard_Real aNewTolerance=sqrt(aD2)+dd;
|
||||
if (aNewTolerance<aMaxTol)
|
||||
UpdateShape(aV, aNewTolerance, aMapToAvoid);
|
||||
}
|
||||
@@ -533,10 +513,10 @@ void CheckEdge (const TopoDS_Edge& Ed,
|
||||
aItPR.Next();
|
||||
}
|
||||
//
|
||||
aOrV=aV.Orientation();
|
||||
TopAbs_Orientation aOrV=aV.Orientation();
|
||||
if (aOrV==TopAbs_FORWARD || aOrV==TopAbs_REVERSED) {
|
||||
Handle(BRep_GCurve) aGC (Handle(BRep_GCurve)::DownCast (aCR));
|
||||
|
||||
gp_Pnt aPC;
|
||||
if (aOrV==TopAbs_FORWARD) {
|
||||
aPC=aC->Value(aGC->First());
|
||||
}
|
||||
@@ -545,9 +525,9 @@ void CheckEdge (const TopoDS_Edge& Ed,
|
||||
}
|
||||
aPC.Transform(L.Transformation());
|
||||
//
|
||||
aD2=aPV.SquareDistance(aPC);
|
||||
Standard_Real aD2=aPV.SquareDistance(aPC);
|
||||
if (aD2 > aTol) {
|
||||
aNewTolerance=sqrt(aD2)+dd;
|
||||
Standard_Real aNewTolerance=sqrt(aD2)+dd;
|
||||
if (aNewTolerance<aMaxTol)
|
||||
UpdateShape(aV, aNewTolerance, aMapToAvoid);
|
||||
}
|
||||
@@ -558,80 +538,6 @@ void CheckEdge (const TopoDS_Edge& Ed,
|
||||
}// while (itcr.More()) {
|
||||
} // for (; aVExp.More(); aVExp.Next()) {
|
||||
}
|
||||
//=======================================================================
|
||||
// Function : CorrectWires
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
void CorrectWires(const TopoDS_Face& aFx,
|
||||
const BOPCol_IndexedMapOfShape& aMapToAvoid)
|
||||
{
|
||||
Standard_Integer i, aNbV;
|
||||
Standard_Real aTol, aTol2, aD2, aD2max, aT1, aT2, aT;
|
||||
gp_Pnt aP, aPV;
|
||||
gp_Pnt2d aP2D;
|
||||
TopoDS_Face aF;
|
||||
TopTools_IndexedDataMapOfShapeListOfShape aMVE;
|
||||
TopTools_ListIteratorOfListOfShape aIt, aIt1;
|
||||
//
|
||||
aF=aFx;
|
||||
aF.Orientation(TopAbs_FORWARD);
|
||||
const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aFx);
|
||||
//
|
||||
TopExp::MapShapesAndAncestors(aF,
|
||||
TopAbs_VERTEX,
|
||||
TopAbs_EDGE,
|
||||
aMVE);
|
||||
NCollection_DataMap<TopoDS_Shape, Standard_Real> aMapEdgeLen;
|
||||
aNbV=aMVE.Extent();
|
||||
for (i=1; i<=aNbV; ++i) {
|
||||
const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMVE.FindKey(i));
|
||||
aPV=BRep_Tool::Pnt(aV);
|
||||
aTol=BRep_Tool::Tolerance(aV);
|
||||
aTol2=aTol*aTol;
|
||||
//
|
||||
aD2max=-1.;
|
||||
const TopTools_ListOfShape& aLE=aMVE.FindFromIndex(i);
|
||||
aIt.Initialize(aLE);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Edge& aE=*(TopoDS_Edge*)(&aIt.Value());
|
||||
const Handle(Geom2d_Curve)& aC2D=
|
||||
BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
|
||||
aT=BRep_Tool::Parameter(aV, aE);
|
||||
//
|
||||
aC2D->D0(aT, aP2D);
|
||||
aS->D0(aP2D.X(), aP2D.Y(), aP);
|
||||
aD2=aPV.SquareDistance(aP);
|
||||
if (aD2>aD2max) {
|
||||
aD2max=aD2;
|
||||
}
|
||||
}
|
||||
//
|
||||
//check wires on self interference by intersecting 2d curves of the edges
|
||||
aIt.Initialize(aLE);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&aIt.Value();
|
||||
//
|
||||
aIt1 = aIt;
|
||||
for (aIt1.Next(); aIt1.More(); aIt1.Next()) {
|
||||
const TopoDS_Edge& aE2 = *(TopoDS_Edge*)&aIt1.Value();
|
||||
//
|
||||
if (aE1.IsSame(aE2)) {
|
||||
continue;
|
||||
}
|
||||
//
|
||||
aD2 = IntersectCurves2d(aV, aF, aS, aE1, aE2, aMapEdgeLen);
|
||||
if (aD2 > aD2max) {
|
||||
aD2max = aD2;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
if (aD2max>aTol2) {
|
||||
aTol = 1.01 * sqrt(aD2max);
|
||||
UpdateShape(aV, aTol, aMapToAvoid);
|
||||
}
|
||||
}// for (i=1; i<=aNbV; ++i) {
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// Function : MapEdgeLength
|
||||
@@ -653,35 +559,48 @@ static Standard_Real MapEdgeLength(const TopoDS_Edge& theEdge,
|
||||
}
|
||||
return *pLen;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// Function : EdgeData
|
||||
// purpose : Structure to store edge data
|
||||
//=======================================================================
|
||||
namespace {
|
||||
struct EdgeData {
|
||||
const TopoDS_Edge* Edge; // Edge
|
||||
Standard_Real VParameter; // Parameter of the vertex on the edge
|
||||
Geom2dAdaptor_Curve GAdaptor; // 2D adaptor for PCurve of the edge on the face
|
||||
Standard_Real First; // First parameter in the range
|
||||
Standard_Real Last; // Last parameter in the rage
|
||||
};
|
||||
}
|
||||
//=======================================================================
|
||||
// Function : IntersectCurves2d
|
||||
// purpose : Intersect 2d curves of edges
|
||||
//=======================================================================
|
||||
Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
|
||||
const TopoDS_Face& theF,
|
||||
const Handle(Geom_Surface)& theS,
|
||||
const TopoDS_Edge& theE1,
|
||||
const TopoDS_Edge& theE2,
|
||||
NCollection_DataMap<TopoDS_Shape, Standard_Real>& theMapEdgeLen)
|
||||
static
|
||||
Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
|
||||
const Handle(Geom_Surface)& theS,
|
||||
const EdgeData& theEData1,
|
||||
const EdgeData& theEData2,
|
||||
NCollection_DataMap<TopoDS_Shape, Standard_Real>& theMapEdgeLen)
|
||||
{
|
||||
Standard_Real aT11, aT12, aT21, aT22, aTol2d, aMaxDist;
|
||||
Geom2dInt_GInter anInter;
|
||||
// Range of the first edge
|
||||
Standard_Real aT11 = theEData1.First;
|
||||
Standard_Real aT12 = theEData1.Last;
|
||||
// Range of the second edge
|
||||
Standard_Real aT21 = theEData2.First;
|
||||
Standard_Real aT22 = theEData2.Last;
|
||||
|
||||
Standard_Real aMaxDist = 0.;
|
||||
Standard_Real aTol2d = 1.e-10;
|
||||
//
|
||||
aMaxDist = 0.;
|
||||
aTol2d = 1.e-10;
|
||||
IntRes2d_Domain aDom1(theEData1.GAdaptor.Value(aT11), aT11, aTol2d,
|
||||
theEData1.GAdaptor.Value(aT12), aT12, aTol2d);
|
||||
IntRes2d_Domain aDom2(theEData2.GAdaptor.Value(aT21), aT21, aTol2d,
|
||||
theEData2.GAdaptor.Value(aT22), aT22, aTol2d);
|
||||
//
|
||||
const Handle(Geom2d_Curve)& aC2D1=
|
||||
BRep_Tool::CurveOnSurface(theE1, theF, aT11, aT12);
|
||||
const Handle(Geom2d_Curve)& aC2D2=
|
||||
BRep_Tool::CurveOnSurface(theE2, theF, aT21, aT22);
|
||||
//
|
||||
Geom2dAdaptor_Curve aGAC1(aC2D1), aGAC2(aC2D2);
|
||||
IntRes2d_Domain aDom1(aC2D1->Value(aT11), aT11, aTol2d,
|
||||
aC2D1->Value(aT12), aT12, aTol2d);
|
||||
IntRes2d_Domain aDom2(aC2D2->Value(aT21), aT21, aTol2d,
|
||||
aC2D2->Value(aT22), aT22, aTol2d);
|
||||
//
|
||||
anInter.Perform(aGAC1, aDom1, aGAC2, aDom2, aTol2d, aTol2d);
|
||||
anInter.Perform(theEData1.GAdaptor, aDom1, theEData2.GAdaptor, aDom2, aTol2d, aTol2d);
|
||||
if (!anInter.IsDone() || (!anInter.NbSegments() && !anInter.NbPoints())) {
|
||||
return aMaxDist;
|
||||
}
|
||||
@@ -694,8 +613,8 @@ Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
|
||||
NCollection_List<IntRes2d_IntersectionPoint>::Iterator aItLP;
|
||||
//
|
||||
aPV = BRep_Tool::Pnt(theV);
|
||||
aT1 = BRep_Tool::Parameter(theV, theE1);
|
||||
aT2 = BRep_Tool::Parameter(theV, theE2);
|
||||
aT1 = theEData1.VParameter;
|
||||
aT2 = theEData2.VParameter;
|
||||
//
|
||||
aHalfR1 = (aT12 - aT11) / 2.;
|
||||
aHalfR2 = (aT22 - aT21) / 2.;
|
||||
@@ -716,8 +635,8 @@ Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
|
||||
}
|
||||
//
|
||||
// evaluate the length of the smallest edge, so that not to return too large distance
|
||||
Standard_Real aLen1 = MapEdgeLength(theE1, theMapEdgeLen);
|
||||
Standard_Real aLen2 = MapEdgeLength(theE2, theMapEdgeLen);
|
||||
Standard_Real aLen1 = MapEdgeLength(*theEData1.Edge, theMapEdgeLen);
|
||||
Standard_Real aLen2 = MapEdgeLength(*theEData1.Edge, theMapEdgeLen);
|
||||
const Standard_Real MaxEdgePartCoveredByVertex = 0.3;
|
||||
Standard_Real aMaxThresDist = Min(aLen1, aLen2) * MaxEdgePartCoveredByVertex;
|
||||
aMaxThresDist *= aMaxThresDist;
|
||||
@@ -750,6 +669,86 @@ Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
|
||||
//
|
||||
return aMaxDist;
|
||||
}
|
||||
//=======================================================================
|
||||
// Function : CorrectWires
|
||||
// purpose :
|
||||
//=======================================================================
|
||||
void CorrectWires(const TopoDS_Face& aFx,
|
||||
const BOPCol_IndexedMapOfShape& aMapToAvoid)
|
||||
{
|
||||
Standard_Integer i, aNbV;
|
||||
Standard_Real aTol, aTol2, aD2, aD2max, aT1, aT2, aT;
|
||||
gp_Pnt aP, aPV;
|
||||
gp_Pnt2d aP2D;
|
||||
TopoDS_Face aF;
|
||||
TopTools_IndexedDataMapOfShapeListOfShape aMVE;
|
||||
TopTools_ListIteratorOfListOfShape aIt;
|
||||
//
|
||||
aF=aFx;
|
||||
aF.Orientation(TopAbs_FORWARD);
|
||||
const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aFx);
|
||||
//
|
||||
TopExp::MapShapesAndAncestors(aF,
|
||||
TopAbs_VERTEX,
|
||||
TopAbs_EDGE,
|
||||
aMVE);
|
||||
NCollection_DataMap<TopoDS_Shape, Standard_Real> aMapEdgeLen;
|
||||
aNbV=aMVE.Extent();
|
||||
for (i=1; i<=aNbV; ++i) {
|
||||
const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMVE.FindKey(i));
|
||||
aPV=BRep_Tool::Pnt(aV);
|
||||
aTol=BRep_Tool::Tolerance(aV);
|
||||
aTol2=aTol*aTol;
|
||||
//
|
||||
aD2max=-1.;
|
||||
// Save edge's data to avoid its recalculation during intersection of 2d curves
|
||||
NCollection_List<EdgeData> aLEPars;
|
||||
const TopTools_ListOfShape& aLE=aMVE.FindFromIndex(i);
|
||||
aIt.Initialize(aLE);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Edge& aE=*(TopoDS_Edge*)(&aIt.Value());
|
||||
const Handle(Geom2d_Curve)& aC2D=
|
||||
BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
|
||||
aT=BRep_Tool::Parameter(aV, aE);
|
||||
//
|
||||
aC2D->D0(aT, aP2D);
|
||||
aS->D0(aP2D.X(), aP2D.Y(), aP);
|
||||
aD2=aPV.SquareDistance(aP);
|
||||
if (aD2>aD2max) {
|
||||
aD2max=aD2;
|
||||
}
|
||||
EdgeData anEData = {&aE, aT, Geom2dAdaptor_Curve(aC2D), aT1, aT2};
|
||||
aLEPars.Append(anEData);
|
||||
}
|
||||
//
|
||||
//check wires on self interference by intersecting 2d curves of the edges
|
||||
NCollection_List<EdgeData>::Iterator aItE1(aLEPars);
|
||||
for (; aItE1.More(); aItE1.Next()) {
|
||||
const EdgeData& aEData1 = aItE1.Value();
|
||||
const TopoDS_Shape& aE1 = *aEData1.Edge;
|
||||
|
||||
NCollection_List<EdgeData>::Iterator aItE2 = aItE1;
|
||||
for (aItE2.Next(); aItE2.More(); aItE2.Next()) {
|
||||
const EdgeData& aEData2 = aItE2.Value();
|
||||
const TopoDS_Shape& aE2 = *aEData2.Edge;
|
||||
|
||||
if (aE1.IsSame(aE2))
|
||||
continue;
|
||||
|
||||
aD2 = IntersectCurves2d(aV, aS, aEData1, aEData2, aMapEdgeLen);
|
||||
if (aD2 > aD2max) {
|
||||
aD2max = aD2;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
if (aD2max>aTol2) {
|
||||
aTol = 1.01 * sqrt(aD2max);
|
||||
UpdateShape(aV, aTol, aMapToAvoid);
|
||||
}
|
||||
}// for (i=1; i<=aNbV; ++i) {
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
// Function : CorrectEdgeTolerance
|
||||
// purpose : Correct tolerances for Edge
|
||||
|
Reference in New Issue
Block a user