1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +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:
emv
2017-10-18 11:05:24 +03:00
committed by bugmaster
parent 3cdf48fe62
commit 98b3765966
37 changed files with 1266 additions and 1315 deletions

View File

@@ -71,38 +71,28 @@ void BOPTools::MapShapesAndAncestors
(const TopoDS_Shape& S,
const TopAbs_ShapeEnum TS,
const TopAbs_ShapeEnum TA,
BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
BOPCol_IndexedDataMapOfShapeListOfShape& Map)
{
TopExp_Explorer aExS, aExA;
//
// visit ancestors
aExA.Init(S, TA);
while (aExA.More()) {
TopExp_Explorer aExA(S, TA);
for (; aExA.More(); aExA.Next())
{
// visit shapes
const TopoDS_Shape& aF = aExA.Current();
const TopoDS_Shape& anAnc = aExA.Current();
//
aExS.Init(aF, TS);
while (aExS.More()) {
const TopoDS_Shape& aE= aExS.Current();
if (aMEF.Contains(aE)) {
aMEF.ChangeFromKey(aE).Append(aF);
}
else {
BOPCol_ListOfShape aLS;
aLS.Append(aF);
aMEF.Add(aE, aLS);
}
aExS.Next();
TopExp_Explorer aExS(anAnc, TS);
for (; aExS.More(); aExS.Next())
{
const TopoDS_Shape& aSS = aExS.Current();
BOPCol_ListOfShape* pLA = Map.ChangeSeek(aSS);
if (!pLA)
pLA = &Map(Map.Add(aSS, BOPCol_ListOfShape()));
pLA->Append(anAnc);
}
aExA.Next();
}
//
// visit shapes not under ancestors
aExS.Init(S, TS, TA);
while (aExS.More()) {
const TopoDS_Shape& aE=aExS.Current();
BOPCol_ListOfShape aLS;
aMEF.Add(aE, aLS);
aExS.Next();
}
TopExp_Explorer aExS(S, TS, TA);
for (; aExS.More(); aExS.Next())
Map.Add(aExS.Current(), BOPCol_ListOfShape());
}

View File

@@ -120,52 +120,149 @@ static
//=======================================================================
void BOPTools_AlgoTools::MakeConnexityBlocks
(const TopoDS_Shape& theS,
const TopAbs_ShapeEnum theType1,
const TopAbs_ShapeEnum theType2,
BOPCol_ListOfShape& theLCB)
const TopAbs_ShapeEnum theConnectionType,
const TopAbs_ShapeEnum theElementType,
BOPCol_ListOfListOfShape& theLCB,
BOPCol_IndexedDataMapOfShapeListOfShape& theConnectionMap)
{
// Map shapes to find connected elements
BOPCol_IndexedDataMapOfShapeListOfShape aDMSLS;
BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aDMSLS);
BOPTools::MapShapesAndAncestors(theS, theConnectionType, theElementType, theConnectionMap);
// Fence map
BOPCol_MapOfShape aMFence;
Standard_Integer i;
BRep_Builder aBB;
//
TopExp_Explorer aExp(theS, theType2);
for (; aExp.More(); aExp.Next()) {
TopExp_Explorer aExp(theS, theElementType);
for (; aExp.More(); aExp.Next())
{
const TopoDS_Shape& aS = aExp.Current();
if (!aMFence.Add(aS)) {
continue;
}
// The block
BOPCol_IndexedMapOfShape aMBlock;
TopoDS_Compound aBlock;
aBB.MakeCompound(aBlock);
BOPCol_ListOfShape aLBlock;
// Start the block
aMBlock.Add(aS);
aBB.Add(aBlock, aS);
aLBlock.Append(aS);
// Look for connected parts
for (i = 1; i <= aMBlock.Extent(); ++i) {
const TopoDS_Shape& aS1 = aMBlock(i);
TopExp_Explorer aExpSS(aS1, theType1);
for (; aExpSS.More(); aExpSS.Next()) {
BOPCol_ListIteratorOfListOfShape aItB(aLBlock);
for (; aItB.More(); aItB.Next())
{
const TopoDS_Shape& aS1 = aItB.Value();
TopExp_Explorer aExpSS(aS1, theConnectionType);
for (; aExpSS.More(); aExpSS.Next())
{
const TopoDS_Shape& aSubS = aExpSS.Current();
const BOPCol_ListOfShape& aLS = aDMSLS.FindFromKey(aSubS);
const BOPCol_ListOfShape& aLS = theConnectionMap.FindFromKey(aSubS);
BOPCol_ListIteratorOfListOfShape aItLS(aLS);
for (; aItLS.More(); aItLS.Next()) {
for (; aItLS.More(); aItLS.Next())
{
const TopoDS_Shape& aS2 = aItLS.Value();
if (aMFence.Add(aS2)) {
aMBlock.Add(aS2);
aBB.Add(aBlock, aS2);
}
if (aMFence.Add(aS2))
aLBlock.Append(aS2);
}
}
}
// Add the block into result
theLCB.Append(aLBlock);
}
}
//=======================================================================
// function: MakeConnexityBlocks
// purpose:
//=======================================================================
void BOPTools_AlgoTools::MakeConnexityBlocks
(const TopoDS_Shape& theS,
const TopAbs_ShapeEnum theConnectionType,
const TopAbs_ShapeEnum theElementType,
BOPCol_ListOfShape& theLCB)
{
BOPCol_ListOfListOfShape aLBlocks;
BOPCol_IndexedDataMapOfShapeListOfShape aCMap;
BOPTools_AlgoTools::MakeConnexityBlocks(theS, theConnectionType, theElementType, aLBlocks, aCMap);
// Make compound from each block
BOPCol_ListIteratorOfListOfListOfShape aItB(aLBlocks);
for (; aItB.More(); aItB.Next())
{
const BOPCol_ListOfShape& aLB = aItB.Value();
TopoDS_Compound aBlock;
BRep_Builder().MakeCompound(aBlock);
for (BOPCol_ListIteratorOfListOfShape it(aLB); it.More(); it.Next())
BRep_Builder().Add(aBlock, it.Value());
theLCB.Append(aBlock);
}
}
//=======================================================================
// function: MakeConnexityBlocks
// purpose:
//=======================================================================
void BOPTools_AlgoTools::MakeConnexityBlocks
(const BOPCol_ListOfShape& theLS,
const TopAbs_ShapeEnum theConnectionType,
const TopAbs_ShapeEnum theElementType,
BOPTools_ListOfConnexityBlock& theLCB)
{
BRep_Builder aBB;
// Make connexity blocks from start elements
TopoDS_Compound aCStart;
aBB.MakeCompound(aCStart);
BOPCol_MapOfShape aMFence, aMNRegular;
BOPCol_ListIteratorOfListOfShape aItL(theLS);
for (; aItL.More(); aItL.Next())
{
const TopoDS_Shape& aS = aItL.Value();
if (aMFence.Add(aS))
aBB.Add(aCStart, aS);
else
aMNRegular.Add(aS);
}
BOPCol_ListOfListOfShape aLCB;
BOPCol_IndexedDataMapOfShapeListOfShape aCMap;
BOPTools_AlgoTools::MakeConnexityBlocks(aCStart, theConnectionType, theElementType, aLCB, aCMap);
// Save the blocks and check their regularity
BOPCol_ListIteratorOfListOfListOfShape aItB(aLCB);
for (; aItB.More(); aItB.Next())
{
const BOPCol_ListOfShape& aBlock = aItB.Value();
BOPTools_ConnexityBlock aCB;
BOPCol_ListOfShape& aLCS = aCB.ChangeShapes();
Standard_Boolean bRegular = Standard_True;
for (BOPCol_ListIteratorOfListOfShape it(aBlock); it.More(); it.Next())
{
TopoDS_Shape aS = it.Value();
if (aMNRegular.Contains(aS))
{
bRegular = Standard_False;
aS.Orientation(TopAbs_FORWARD);
aLCS.Append(aS);
aS.Orientation(TopAbs_REVERSED);
aLCS.Append(aS);
}
else
{
aLCS.Append(aS);
if (bRegular)
{
// Check if there are no multi-connected shapes
for (TopExp_Explorer ex(aS, theConnectionType); ex.More() && bRegular; ex.Next())
bRegular = (aCMap.FindFromKey(ex.Current()).Extent() == 2);
}
}
}
aCB.SetRegular(bRegular);
theLCB.Append(aCB);
}
}
//=======================================================================
// function: OrientEdgesOnWire
// purpose: Reorient edges on wire for correct ordering

View File

@@ -28,7 +28,9 @@
#include <Standard_Boolean.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <BOPTools_ListOfCoupleOfShape.hxx>
#include <BOPTools_ListOfConnexityBlock.hxx>
#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
#include <BOPCol_ListOfListOfShape.hxx>
#include <TopAbs_State.hxx>
#include <BOPCol_IndexedMapOfShape.hxx>
#include <BOPCol_BaseAllocator.hxx>
@@ -188,11 +190,34 @@ public:
//! theMapAvoid - set of edges to avoid for
//! the treatment
Standard_EXPORT static void MakeConnexityBlock (BOPCol_ListOfShape& theLS, BOPCol_IndexedMapOfShape& theMapAvoid, BOPCol_ListOfShape& theLSCB, const BOPCol_BaseAllocator& theAllocator);
//! For the compound theS build the blocks
//! theLCB (as list of compounds)
//! in terms of connexity by the shapes of theType
Standard_EXPORT static void MakeConnexityBlocks (const TopoDS_Shape& theS, const TopAbs_ShapeEnum theType1, const TopAbs_ShapeEnum theType2, BOPCol_ListOfShape& theLCB);
//! For the compound <theS> builds the blocks (compounds) of
//! elements of type <theElementType> connected through the shapes
//! of the type <theConnectionType>.
//! The blocks are stored into the list <theLCB>.
Standard_EXPORT static void MakeConnexityBlocks(const TopoDS_Shape& theS,
const TopAbs_ShapeEnum theConnectionType,
const TopAbs_ShapeEnum theElementType,
BOPCol_ListOfShape& theLCB);
//! For the compound <theS> builds the blocks (compounds) of
//! elements of type <theElementType> connected through the shapes
//! of the type <theConnectionType>.
//! The blocks are stored into the list of lists <theLCB>.
//! Returns also the connection map <theConnectionMap>, filled during operation.
Standard_EXPORT static void MakeConnexityBlocks(const TopoDS_Shape& theS,
const TopAbs_ShapeEnum theConnectionType,
const TopAbs_ShapeEnum theElementType,
BOPCol_ListOfListOfShape& theLCB,
BOPCol_IndexedDataMapOfShapeListOfShape& theConnectionMap);
//! Makes connexity blocks of elements of the given type with the given type of the
//! connecting elements. The blocks are checked on regularity (multi-connectivity)
//! and stored to the list of blocks <theLCB>.
Standard_EXPORT static void MakeConnexityBlocks(const BOPCol_ListOfShape& theLS,
const TopAbs_ShapeEnum theConnectionType,
const TopAbs_ShapeEnum theElementType,
BOPTools_ListOfConnexityBlock& theLCB);
//! Correctly orients edges on the wire
Standard_EXPORT static void OrientEdgesOnWire (TopoDS_Shape& theWire);

View File

@@ -66,9 +66,6 @@
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
static
Standard_Boolean CheckEdgeLength (const TopoDS_Edge& );
static
Handle(Geom2d_Curve) BRep_Tool_CurveOnSurface(const TopoDS_Edge& ,
const TopoDS_Face& ,
@@ -132,9 +129,6 @@ Standard_Boolean BOPTools_AlgoTools2D::EdgeTangent
if (isdgE) {
return Standard_False;
}
if (!CheckEdgeLength(anEdge)) {
return Standard_False;
}
Handle(Geom_Curve) aC=BRep_Tool::Curve(anEdge, first, last);
gp_Pnt aP;
@@ -709,44 +703,6 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
}
}
//=======================================================================
//function : CheckEdgeLength
//purpose :
//=======================================================================
Standard_Boolean CheckEdgeLength (const TopoDS_Edge& E)
{
BRepAdaptor_Curve BC(E);
BOPCol_IndexedMapOfShape aM;
BOPTools::MapShapes(E, TopAbs_VERTEX, aM);
Standard_Integer i, anExtent, aN=10;
Standard_Real ln=0., d, t, f, l, dt;
anExtent=aM.Extent();
if (anExtent!=1)
return Standard_True;
gp_Pnt p1, p2;
f = BC.FirstParameter();
l = BC.LastParameter();
dt=(l-f)/aN;
BC.D0(f, p1);
for (i=1; i<=aN; i++) {
t=f+i*dt;
if (i==aN)
BC.D0(l, p2);
else
BC.D0(t, p2);
d=p1.Distance(p2);
ln+=d;
p1=p2;
}
//
return (ln > Precision::Confusion());
}
//=======================================================================
//function : BRep_Tool_CurveOnSurface
//purpose :

View File

@@ -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