mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
The following improvements have been made in Boolean operations algorithm in order to fix the problem: 1. Initialization of the pave blocks which vertices have acquired the SD ones. 2. Removing from Data Structure the small edges having the same vertices on both ends (either initially or acquired). 3. Avoid adding empty SD connections when one vertex points to itself. Test case for the issue.
1122 lines
37 KiB
C++
1122 lines
37 KiB
C++
// Created by: Peter KURNEV
|
|
// Copyright (c) 2010-2014 OPEN CASCADE SAS
|
|
// Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
|
|
// Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
|
|
// EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
|
|
#include <Bnd_Box.hxx>
|
|
#include <BOPAlgo_PaveFiller.hxx>
|
|
#include <BOPAlgo_Tools.hxx>
|
|
#include <BOPAlgo_Alerts.hxx>
|
|
#include <BOPDS_CommonBlock.hxx>
|
|
#include <BOPDS_CoupleOfPaveBlocks.hxx>
|
|
#include <BOPDS_DS.hxx>
|
|
#include <BOPDS_Interf.hxx>
|
|
#include <BOPDS_Iterator.hxx>
|
|
#include <BOPDS_MapOfPaveBlock.hxx>
|
|
#include <BOPDS_Pave.hxx>
|
|
#include <BOPDS_PaveBlock.hxx>
|
|
#include <BOPDS_VectorOfInterfEE.hxx>
|
|
#include <BOPTools_AlgoTools.hxx>
|
|
#include <BOPTools_AlgoTools2D.hxx>
|
|
#include <BOPTools_Parallel.hxx>
|
|
#include <BndLib_Add3dCurve.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRep_Builder.hxx>
|
|
#include <BRepAdaptor_Curve.hxx>
|
|
#include <GeomAPI_ProjectPointOnCurve.hxx>
|
|
#include <gp_Pnt.hxx>
|
|
#include <IntTools_CommonPrt.hxx>
|
|
#include <IntTools_Context.hxx>
|
|
#include <IntTools_EdgeEdge.hxx>
|
|
#include <IntTools_Range.hxx>
|
|
#include <IntTools_SequenceOfCommonPrts.hxx>
|
|
#include <IntTools_SequenceOfRanges.hxx>
|
|
#include <IntTools_ShrunkRange.hxx>
|
|
#include <IntTools_Tools.hxx>
|
|
#include <NCollection_IncAllocator.hxx>
|
|
#include <NCollection_Vector.hxx>
|
|
#include <Precision.hxx>
|
|
#include <TopoDS.hxx>
|
|
#include <TopoDS_Edge.hxx>
|
|
#include <TopoDS_Vertex.hxx>
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//=======================================================================
|
|
//class : BOPAlgo_EdgeEdge
|
|
//purpose :
|
|
//=======================================================================
|
|
class BOPAlgo_EdgeEdge :
|
|
public IntTools_EdgeEdge,
|
|
public BOPAlgo_Algo {
|
|
|
|
public:
|
|
|
|
DEFINE_STANDARD_ALLOC
|
|
//
|
|
BOPAlgo_EdgeEdge():
|
|
IntTools_EdgeEdge(),
|
|
BOPAlgo_Algo() {
|
|
};
|
|
//
|
|
virtual ~BOPAlgo_EdgeEdge(){
|
|
};
|
|
//
|
|
void SetPaveBlock1(const Handle(BOPDS_PaveBlock)& aPB) {
|
|
myPB1=aPB;
|
|
}
|
|
//
|
|
Handle(BOPDS_PaveBlock)& PaveBlock1() {
|
|
return myPB1;
|
|
}
|
|
//
|
|
void SetPaveBlock2(const Handle(BOPDS_PaveBlock)& aPB) {
|
|
myPB2=aPB;
|
|
}
|
|
//
|
|
Handle(BOPDS_PaveBlock)& PaveBlock2() {
|
|
return myPB2;
|
|
}
|
|
//
|
|
void SetFuzzyValue(const Standard_Real theFuzz) {
|
|
IntTools_EdgeEdge::SetFuzzyValue(theFuzz);
|
|
}
|
|
//
|
|
virtual void Perform() {
|
|
BOPAlgo_Algo::UserBreak();
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
|
|
IntTools_EdgeEdge::Perform();
|
|
}
|
|
catch (Standard_Failure)
|
|
{
|
|
AddError(new BOPAlgo_AlertIntersectionFailed);
|
|
}
|
|
}
|
|
//
|
|
protected:
|
|
Handle(BOPDS_PaveBlock) myPB1;
|
|
Handle(BOPDS_PaveBlock) myPB2;
|
|
};
|
|
//
|
|
//=======================================================================
|
|
typedef NCollection_Vector
|
|
<BOPAlgo_EdgeEdge> BOPAlgo_VectorOfEdgeEdge;
|
|
//
|
|
typedef BOPTools_Functor
|
|
<BOPAlgo_EdgeEdge,
|
|
BOPAlgo_VectorOfEdgeEdge> BOPAlgo_EdgeEdgeFunctor;
|
|
//
|
|
typedef BOPTools_Cnt
|
|
<BOPAlgo_EdgeEdgeFunctor,
|
|
BOPAlgo_VectorOfEdgeEdge> BOPAlgo_EdgeEdgeCnt;
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//=======================================================================
|
|
// function: PerformEE
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PerformEE()
|
|
{
|
|
FillShrunkData(TopAbs_EDGE, TopAbs_EDGE);
|
|
//
|
|
myIterator->Initialize(TopAbs_EDGE, TopAbs_EDGE);
|
|
Standard_Integer iSize = myIterator->ExpectedLength();
|
|
if (!iSize) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Boolean bExpressCompute, bIsPBSplittable1, bIsPBSplittable2;
|
|
Standard_Integer i, iX, nE1, nE2, aNbCPrts, k, aNbEdgeEdge;
|
|
Standard_Integer nV11, nV12, nV21, nV22;
|
|
Standard_Real aTS11, aTS12, aTS21, aTS22, aT11, aT12, aT21, aT22;
|
|
TopAbs_ShapeEnum aType;
|
|
BOPDS_ListIteratorOfListOfPaveBlock aIt1, aIt2;
|
|
Handle(NCollection_BaseAllocator) aAllocator;
|
|
BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
|
|
BOPDS_MapIteratorOfMapOfPaveBlock aItPB;
|
|
// keep modified edges for further update
|
|
TColStd_MapOfInteger aMEdges;
|
|
//
|
|
aAllocator=NCollection_BaseAllocator::CommonBaseAllocator();
|
|
//-----------------------------------------------------scope f
|
|
BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(100, aAllocator);
|
|
BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aMVCPB(100, aAllocator);
|
|
BOPAlgo_DataMapOfPaveBlockBndBox aDMPBBox(100, aAllocator);
|
|
//
|
|
BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
|
|
aEEs.SetIncrement(iSize);
|
|
//
|
|
for (; myIterator->More(); myIterator->Next()) {
|
|
myIterator->Value(nE1, nE2);
|
|
//
|
|
const BOPDS_ShapeInfo& aSIE1=myDS->ShapeInfo(nE1);
|
|
if (aSIE1.HasFlag()){
|
|
continue;
|
|
}
|
|
const BOPDS_ShapeInfo& aSIE2=myDS->ShapeInfo(nE2);
|
|
if (aSIE2.HasFlag()){
|
|
continue;
|
|
}
|
|
//
|
|
BOPDS_ListOfPaveBlock& aLPB1 = myDS->ChangePaveBlocks(nE1);
|
|
if (aLPB1.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
BOPDS_ListOfPaveBlock& aLPB2 = myDS->ChangePaveBlocks(nE2);
|
|
if (aLPB2.IsEmpty()) {
|
|
continue;
|
|
}
|
|
//
|
|
const TopoDS_Edge& aE1=(*(TopoDS_Edge *)(&aSIE1.Shape()));
|
|
const TopoDS_Edge& aE2=(*(TopoDS_Edge *)(&aSIE2.Shape()));
|
|
//
|
|
aIt1.Initialize(aLPB1);
|
|
for (; aIt1.More(); aIt1.Next()) {
|
|
Bnd_Box aBB1;
|
|
//
|
|
Handle(BOPDS_PaveBlock)& aPB1=aIt1.ChangeValue();
|
|
//
|
|
if (!GetPBBox(aE1, aPB1, aDMPBBox, aT11, aT12, aTS11, aTS12, aBB1)) {
|
|
continue;
|
|
}
|
|
//
|
|
aPB1->Indices(nV11, nV12);
|
|
//
|
|
aIt2.Initialize(aLPB2);
|
|
for (; aIt2.More(); aIt2.Next()) {
|
|
Bnd_Box aBB2;
|
|
//
|
|
Handle(BOPDS_PaveBlock)& aPB2=aIt2.ChangeValue();
|
|
//
|
|
if (!GetPBBox(aE2, aPB2, aDMPBBox, aT21, aT22, aTS21, aTS22, aBB2)) {
|
|
continue;
|
|
}
|
|
//
|
|
if (aBB1.IsOut(aBB2)) {
|
|
continue;
|
|
}
|
|
//
|
|
aPB2->Indices(nV21, nV22);
|
|
//
|
|
bExpressCompute=((nV11==nV21 && nV12==nV22) ||
|
|
(nV12==nV21 && nV11==nV22));
|
|
//
|
|
BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge.Appended();
|
|
//
|
|
anEdgeEdge.UseQuickCoincidenceCheck(bExpressCompute);
|
|
//
|
|
anEdgeEdge.SetPaveBlock1(aPB1);
|
|
anEdgeEdge.SetPaveBlock2(aPB2);
|
|
//
|
|
anEdgeEdge.SetEdge1(aE1, aT11, aT12);
|
|
anEdgeEdge.SetEdge2(aE2, aT21, aT22);
|
|
anEdgeEdge.SetFuzzyValue(myFuzzyValue);
|
|
anEdgeEdge.SetProgressIndicator(myProgressIndicator);
|
|
}//for (; aIt2.More(); aIt2.Next()) {
|
|
}//for (; aIt1.More(); aIt1.Next()) {
|
|
}//for (; myIterator->More(); myIterator->Next()) {
|
|
//
|
|
aNbEdgeEdge=aVEdgeEdge.Length();
|
|
//======================================================
|
|
BOPAlgo_EdgeEdgeCnt::Perform(myRunParallel, aVEdgeEdge);
|
|
//======================================================
|
|
//
|
|
for (k = 0; k < aNbEdgeEdge; ++k) {
|
|
Bnd_Box aBB1, aBB2;
|
|
//
|
|
BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge(k);
|
|
if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors()) {
|
|
// Warn about failed intersection of sub-shapes
|
|
const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
|
|
const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
|
|
AddIntersectionFailedWarning(aE1, aE2);
|
|
continue;
|
|
}
|
|
//
|
|
const IntTools_SequenceOfCommonPrts& aCPrts = anEdgeEdge.CommonParts();
|
|
aNbCPrts = aCPrts.Length();
|
|
if (!aNbCPrts) {
|
|
continue;
|
|
}
|
|
//--------------------------------------------
|
|
Handle(BOPDS_PaveBlock)& aPB1=anEdgeEdge.PaveBlock1();
|
|
nE1=aPB1->OriginalEdge();
|
|
aPB1->Range(aT11, aT12);
|
|
if (!aPB1->HasShrunkData()) {
|
|
aTS11 = aT11;
|
|
aTS12 = aT12;
|
|
bIsPBSplittable1 = Standard_False;
|
|
}
|
|
else {
|
|
aPB1->ShrunkData(aTS11, aTS12, aBB1, bIsPBSplittable1);
|
|
}
|
|
//
|
|
Handle(BOPDS_PaveBlock)& aPB2=anEdgeEdge.PaveBlock2();
|
|
nE2=aPB2->OriginalEdge();
|
|
aPB2->Range(aT21, aT22);
|
|
if (!aPB2->HasShrunkData()) {
|
|
aTS21 = aT21;
|
|
aTS22 = aT22;
|
|
bIsPBSplittable2 = Standard_False;
|
|
}
|
|
else {
|
|
aPB2->ShrunkData(aTS21, aTS22, aBB2, bIsPBSplittable2);
|
|
}
|
|
//
|
|
//--------------------------------------------
|
|
IntTools_Range aR11(aT11, aTS11), aR12(aTS12, aT12),
|
|
aR21(aT21, aTS21), aR22(aTS22, aT22);
|
|
//
|
|
Standard_Boolean bAnalytical = Standard_False;
|
|
{
|
|
const TopoDS_Edge& aOE1 = *(TopoDS_Edge*)&myDS->Shape(nE1);
|
|
const TopoDS_Edge& aOE2 = *(TopoDS_Edge*)&myDS->Shape(nE2);
|
|
//
|
|
BRepAdaptor_Curve aBAC1(aOE1), aBAC2(aOE2);
|
|
//
|
|
GeomAbs_CurveType aType1 = aBAC1.GetType();
|
|
GeomAbs_CurveType aType2 = aBAC2.GetType();
|
|
//
|
|
bAnalytical = (((aType1 == GeomAbs_Line) &&
|
|
(aType2 == GeomAbs_Line ||
|
|
aType2 == GeomAbs_Circle)) ||
|
|
((aType2 == GeomAbs_Line) &&
|
|
(aType1 == GeomAbs_Line ||
|
|
aType1 == GeomAbs_Circle)));
|
|
}
|
|
//
|
|
for (i=1; i<=aNbCPrts; ++i) {
|
|
const IntTools_CommonPrt& aCPart=aCPrts(i);
|
|
//
|
|
const TopoDS_Edge& aE1=aCPart.Edge1();
|
|
const TopoDS_Edge& aE2=aCPart.Edge2();
|
|
//
|
|
aType=aCPart.Type();
|
|
switch (aType) {
|
|
case TopAbs_VERTEX: {
|
|
if (!bIsPBSplittable1 || !bIsPBSplittable2) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean bIsOnPave[4];
|
|
Standard_Integer nV[4], j;
|
|
Standard_Real aT1, aT2, aTol;
|
|
TopoDS_Vertex aVnew;
|
|
IntTools_Range aCR1, aCR2;
|
|
//
|
|
IntTools_Tools::VertexParameters(aCPart, aT1, aT2);
|
|
aTol = Precision::Confusion();
|
|
aCR1 = aCPart.Range1();
|
|
aCR2 = aCPart.Ranges2()(1);
|
|
//
|
|
//decide to keep the pave or not
|
|
bIsOnPave[0] = IntTools_Tools::IsOnPave1(aT1, aR11, aTol) ||
|
|
IntTools_Tools::IsOnPave1(aR11.First(), aCR1, aTol);
|
|
bIsOnPave[1] = IntTools_Tools::IsOnPave1(aT1, aR12, aTol) ||
|
|
IntTools_Tools::IsOnPave1(aR12.Last(), aCR1, aTol);
|
|
bIsOnPave[2] = IntTools_Tools::IsOnPave1(aT2, aR21, aTol) ||
|
|
IntTools_Tools::IsOnPave1(aR21.First(), aCR2, aTol);
|
|
bIsOnPave[3] = IntTools_Tools::IsOnPave1(aT2, aR22, aTol) ||
|
|
IntTools_Tools::IsOnPave1(aR22.Last(), aCR2, aTol);
|
|
//
|
|
aPB1->Indices(nV[0], nV[1]);
|
|
aPB2->Indices(nV[2], nV[3]);
|
|
//
|
|
if((bIsOnPave[0] && bIsOnPave[2]) ||
|
|
(bIsOnPave[0] && bIsOnPave[3]) ||
|
|
(bIsOnPave[1] && bIsOnPave[2]) ||
|
|
(bIsOnPave[1] && bIsOnPave[3])) {
|
|
continue;
|
|
}
|
|
//
|
|
Standard_Boolean isVExists = Standard_False;
|
|
for (j = 0; j < 4; ++j)
|
|
{
|
|
if (bIsOnPave[j])
|
|
{
|
|
Handle(BOPDS_PaveBlock)& aPB = (j < 2) ? aPB2 : aPB1;
|
|
bIsOnPave[j] = ForceInterfVE(nV[j], aPB, aMEdges);
|
|
if (bIsOnPave[j]) isVExists = Standard_True;
|
|
}
|
|
}
|
|
|
|
BOPTools_AlgoTools::MakeNewVertex(aE1, aT1, aE2, aT2, aVnew);
|
|
const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
|
|
|
|
if (isVExists)
|
|
{
|
|
// The found intersection point is located closely to one of the
|
|
// pave blocks bounds. So, do not create the new vertex in this point.
|
|
// Check if this point is a real intersection point or just a touching point.
|
|
// If it is a touching point, do nothing.
|
|
// If it is an intersection point, update the existing vertex to cover the
|
|
// intersection point.
|
|
const gp_Pnt aPOnE1 = BRepAdaptor_Curve(aE1).Value(aT1);
|
|
const gp_Pnt aPOnE2 = BRepAdaptor_Curve(aE2).Value(aT2);
|
|
if (aPOnE1.Distance(aPOnE2) > Precision::Intersection())
|
|
// No intersection point
|
|
continue;
|
|
|
|
// Real intersection is present.
|
|
// Update the existing vertex to cover the intersection point.
|
|
for (j = 0; j < 4; ++j)
|
|
{
|
|
if (bIsOnPave[j])
|
|
{
|
|
const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
|
|
const gp_Pnt aP = BRep_Tool::Pnt(aV);
|
|
Standard_Real aDistPP = aP.Distance(aPnew);
|
|
// Just update the vertex
|
|
UpdateVertex(nV[j], aDistPP);
|
|
myVertsToAvoidExtension.Add(nV[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
|
|
if (bAnalytical) {
|
|
// increase tolerance for Line/Line intersection, but do not update
|
|
// the vertex till its intersection with some other shape
|
|
Standard_Real aTolMin = (BRepAdaptor_Curve(aE1).GetType() == GeomAbs_Line) ?
|
|
(aCR1.Last() - aCR1.First()) / 2. : (aCR2.Last() - aCR2.First()) / 2.;
|
|
if (aTolMin > aTolVnew) {
|
|
aTolVnew = aTolMin;
|
|
}
|
|
}
|
|
// <-LXBR
|
|
{
|
|
Standard_Integer nVS[2], iFound;
|
|
Standard_Real aTolVx, aD2, aDT2;
|
|
TColStd_MapOfInteger aMV;
|
|
gp_Pnt aPx;
|
|
//
|
|
iFound=0;
|
|
j=-1;
|
|
aMV.Add(nV[0]);
|
|
aMV.Add(nV[1]);
|
|
//
|
|
if (aMV.Contains(nV[2])) {
|
|
++j;
|
|
nVS[j]=nV[2];
|
|
}
|
|
if (aMV.Contains(nV[3])) {
|
|
++j;
|
|
nVS[j]=nV[3];
|
|
}
|
|
//
|
|
for (Standard_Integer k1=0; k1<=j; ++k1) {
|
|
const TopoDS_Vertex& aVx= *(TopoDS_Vertex*)&(myDS->Shape(nVS[k1]));
|
|
aTolVx=BRep_Tool::Tolerance(aVx);
|
|
aPx=BRep_Tool::Pnt(aVx);
|
|
aD2=aPnew.SquareDistance(aPx);
|
|
//
|
|
aDT2=100.*(aTolVnew+aTolVx)*(aTolVnew+aTolVx);
|
|
//
|
|
if (aD2<aDT2) {
|
|
iFound=1;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
if (iFound) {
|
|
continue;
|
|
}
|
|
}
|
|
//
|
|
// 1
|
|
BOPDS_InterfEE& aEE=aEEs.Appended();
|
|
iX=aEEs.Length()-1;
|
|
aEE.SetIndices(nE1, nE2);
|
|
aEE.SetCommonPart(aCPart);
|
|
// 2
|
|
myDS->AddInterf(nE1, nE2);
|
|
//
|
|
BOPDS_CoupleOfPaveBlocks aCPB;
|
|
//
|
|
aCPB.SetPaveBlocks(aPB1, aPB2);
|
|
aCPB.SetIndexInterf(iX);
|
|
aCPB.SetTolerance(aTolVnew);
|
|
aMVCPB.Add(aVnew, aCPB);
|
|
}//case TopAbs_VERTEX:
|
|
break;
|
|
//
|
|
case TopAbs_EDGE: {
|
|
if (aNbCPrts > 1) {
|
|
break;
|
|
}
|
|
//
|
|
Standard_Boolean bHasSameBounds;
|
|
bHasSameBounds=aPB1->HasSameBounds(aPB2);
|
|
if (!bHasSameBounds) {
|
|
break;
|
|
}
|
|
// 1
|
|
BOPDS_InterfEE& aEE=aEEs.Appended();
|
|
iX=aEEs.Length()-1;
|
|
aEE.SetIndices(nE1, nE2);
|
|
aEE.SetCommonPart(aCPart);
|
|
// 2
|
|
myDS->AddInterf(nE1, nE2);
|
|
//
|
|
BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock), TColStd_MapTransientHasher>(aPB1, aPB2, aMPBLPB, aAllocator);
|
|
}//case TopAbs_EDGE
|
|
break;
|
|
default:
|
|
break;
|
|
}//switch (aType) {
|
|
}//for (i=1; i<=aNbCPrts; i++) {
|
|
}//for (k=0; k < aNbFdgeEdge; ++k) {
|
|
//
|
|
//=========================================
|
|
// post treatment
|
|
//=========================================
|
|
BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS, myContext);
|
|
// Update vertices of common blocks with real CB tolerances
|
|
UpdateVerticesOfCB();
|
|
|
|
PerformNewVertices(aMVCPB, aAllocator);
|
|
//
|
|
if (aMEdges.Extent()) {
|
|
Standard_Integer aNbV = aMVCPB.Extent();
|
|
for (i = 1; i <= aNbV; ++i) {
|
|
Handle(BOPDS_PaveBlock) aPB1, aPB2;
|
|
const BOPDS_CoupleOfPaveBlocks& aCPB = aMVCPB.FindFromIndex(i);
|
|
aCPB.PaveBlocks(aPB1, aPB2);
|
|
//
|
|
aMEdges.Remove(aPB1->OriginalEdge());
|
|
aMEdges.Remove(aPB2->OriginalEdge());
|
|
}
|
|
//
|
|
SplitPaveBlocks(aMEdges, Standard_False);
|
|
}
|
|
//
|
|
//-----------------------------------------------------scope t
|
|
aMPBLPB.Clear();
|
|
aMVCPB.Clear();
|
|
}
|
|
//=======================================================================
|
|
//function : PerformVerticesEE
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::PerformNewVertices
|
|
(BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB,
|
|
const Handle(NCollection_BaseAllocator)& theAllocator,
|
|
const Standard_Boolean bIsEEIntersection)
|
|
{
|
|
Standard_Integer aNbV = theMVCPB.Extent();
|
|
if (!aNbV) {
|
|
return;
|
|
}
|
|
//
|
|
Standard_Real aTolAdd = myFuzzyValue / 2.;
|
|
//
|
|
// 1. Fuse the new vertices
|
|
TopTools_IndexedDataMapOfShapeListOfShape aImages;
|
|
TreatNewVertices(theMVCPB, aImages);
|
|
//
|
|
// 2. Add new vertices to myDS and connect indices to CPB structure
|
|
BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
|
|
BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
|
|
//
|
|
Standard_Integer i, aNb = aImages.Extent();
|
|
for (i = 1; i <= aNb; ++i) {
|
|
const TopoDS_Vertex& aV = TopoDS::Vertex(aImages.FindKey(i));
|
|
const TopTools_ListOfShape& aLVSD = aImages.FindFromIndex(i);
|
|
//
|
|
BOPDS_ShapeInfo aSI;
|
|
aSI.SetShapeType(TopAbs_VERTEX);
|
|
aSI.SetShape(aV);
|
|
Standard_Integer iV = myDS->Append(aSI);
|
|
//
|
|
BOPDS_ShapeInfo& aSIDS = myDS->ChangeShapeInfo(iV);
|
|
Bnd_Box& aBox = aSIDS.ChangeBox();
|
|
aBox.Add(BRep_Tool::Pnt(aV));
|
|
aBox.SetGap(BRep_Tool::Tolerance(aV) + aTolAdd);
|
|
//
|
|
TopTools_ListIteratorOfListOfShape aItLS(aLVSD);
|
|
for (; aItLS.More(); aItLS.Next()) {
|
|
const TopoDS_Shape& aVx = aItLS.Value();
|
|
BOPDS_CoupleOfPaveBlocks &aCPB = theMVCPB.ChangeFromKey(aVx);
|
|
aCPB.SetIndex(iV);
|
|
// update interference
|
|
Standard_Integer iX = aCPB.IndexInterf();
|
|
BOPDS_Interf *aInt = bIsEEIntersection ? (BOPDS_Interf*)(&aEEs(iX)) : (BOPDS_Interf*) (&aEFs(iX));
|
|
aInt->SetIndexNew(iV);
|
|
}
|
|
}
|
|
//
|
|
// 3. Map PaveBlock/ListOfVertices to add to this PaveBlock ->aMPBLI
|
|
BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(100, theAllocator);
|
|
for (i = 1; i <= aNbV; ++i) {
|
|
const BOPDS_CoupleOfPaveBlocks& aCPB = theMVCPB.FindFromIndex(i);
|
|
Standard_Integer iV = aCPB.Index();
|
|
//
|
|
Handle(BOPDS_PaveBlock) aPB[2];
|
|
aCPB.PaveBlocks(aPB[0], aPB[1]);
|
|
for (Standard_Integer j = 0; j < 2; ++j) {
|
|
TColStd_ListOfInteger *pLI = aMPBLI.ChangeSeek(aPB[j]);
|
|
if (!pLI) {
|
|
pLI = &aMPBLI(aMPBLI.Add(aPB[j], TColStd_ListOfInteger(theAllocator)));
|
|
}
|
|
pLI->Append(iV);
|
|
//
|
|
if (aPB[0] == aPB[1]) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// 4. Compute Extra Paves and split Pave blocks by the Extra paves
|
|
IntersectVE(aMPBLI, Standard_False);
|
|
}
|
|
//=======================================================================
|
|
//function : TreatNewVertices
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::TreatNewVertices
|
|
(const BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB,
|
|
TopTools_IndexedDataMapOfShapeListOfShape& myImages)
|
|
{
|
|
//
|
|
// Prepare for intersection
|
|
TopTools_IndexedDataMapOfShapeReal aVerts;
|
|
Standard_Integer i, aNbV = theMVCPB.Extent();
|
|
for (i = 1; i <= aNbV; ++i) {
|
|
const TopoDS_Shape& aV = theMVCPB.FindKey(i);
|
|
Standard_Real aTol = theMVCPB.FindFromIndex(i).Tolerance();
|
|
aVerts.Add(aV, aTol);
|
|
}
|
|
//
|
|
// Perform intersection
|
|
TopTools_ListOfListOfShape aChains;
|
|
BOPAlgo_Tools::IntersectVertices(aVerts, myRunParallel, myFuzzyValue, aChains);
|
|
//
|
|
// Treat the results - make new vertices for each chain
|
|
TopTools_ListOfListOfShape::Iterator aItC(aChains);
|
|
for (; aItC.More(); aItC.Next()) {
|
|
const TopTools_ListOfShape& aLVSD = aItC.Value();
|
|
//
|
|
TopoDS_Vertex aVNew;
|
|
BOPTools_AlgoTools::MakeVertex(aLVSD, aVNew);
|
|
myImages.Add(aVNew, aLVSD);
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : FillShrunkData
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::FillShrunkData(Handle(BOPDS_PaveBlock)& thePB)
|
|
{
|
|
// Vertices
|
|
Standard_Integer nV1, nV2;
|
|
thePB->Indices(nV1, nV2);
|
|
const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
|
|
const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
|
|
// Get the edge
|
|
Standard_Integer nE = -1;
|
|
if (!thePB->HasEdge(nE))
|
|
{
|
|
nE = thePB->OriginalEdge();
|
|
if (nE < 0)
|
|
return;
|
|
}
|
|
|
|
const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
|
|
// Range
|
|
Standard_Real aT1, aT2;
|
|
thePB->Range(aT1, aT2);
|
|
//
|
|
IntTools_ShrunkRange aSR;
|
|
aSR.SetContext(myContext);
|
|
aSR.SetData(aE, aT1, aT2, aV1, aV2);
|
|
aSR.Perform();
|
|
// Analyze the results of computations
|
|
AnalyzeShrunkData(thePB, aSR);
|
|
}
|
|
//=======================================================================
|
|
// function: AnalyzeShrunkData
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::AnalyzeShrunkData(const Handle(BOPDS_PaveBlock)& thePB,
|
|
const IntTools_ShrunkRange& theSR)
|
|
{
|
|
// in case of error treat the warning status
|
|
Standard_Boolean bWholeEdge = Standard_False;
|
|
TopoDS_Shape aWarnShape;
|
|
//
|
|
if (!theSR.IsDone() || !theSR.IsSplittable()) {
|
|
Standard_Real aEFirst, aELast, aPBFirst, aPBLast;
|
|
BRep_Tool::Range(theSR.Edge(), aEFirst, aELast);
|
|
thePB->Range(aPBFirst, aPBLast);
|
|
bWholeEdge = !(aPBFirst > aEFirst || aPBLast < aELast);
|
|
if (bWholeEdge && thePB->OriginalEdge() >= 0) {
|
|
aWarnShape = theSR.Edge();
|
|
}
|
|
else {
|
|
const TopoDS_Shape& aV1 = myDS->Shape(thePB->Pave1().Index());
|
|
const TopoDS_Shape& aV2 = myDS->Shape(thePB->Pave2().Index());
|
|
BRep_Builder().MakeCompound(TopoDS::Compound(aWarnShape));
|
|
BRep_Builder().Add(aWarnShape, theSR.Edge());
|
|
BRep_Builder().Add(aWarnShape, aV1);
|
|
BRep_Builder().Add(aWarnShape, aV2);
|
|
}
|
|
//
|
|
if (!theSR.IsDone()) {
|
|
if (bWholeEdge)
|
|
AddWarning (new BOPAlgo_AlertTooSmallEdge (aWarnShape));
|
|
else
|
|
AddWarning (new BOPAlgo_AlertBadPositioning (aWarnShape));
|
|
Standard_Real aTS1, aTS2;
|
|
theSR.ShrunkRange(aTS1, aTS2);
|
|
thePB->SetShrunkData(aTS1, aTS2, Bnd_Box(), Standard_False);
|
|
return;
|
|
}
|
|
//
|
|
if (bWholeEdge)
|
|
AddWarning (new BOPAlgo_AlertNotSplittableEdge (aWarnShape));
|
|
else
|
|
AddWarning (new BOPAlgo_AlertBadPositioning (aWarnShape));
|
|
}
|
|
//
|
|
Standard_Real aTS1, aTS2;
|
|
theSR.ShrunkRange(aTS1, aTS2);
|
|
Bnd_Box aBox = theSR.BndBox();
|
|
aBox.SetGap(aBox.GetGap() + myFuzzyValue / 2.);
|
|
thePB->SetShrunkData(aTS1, aTS2, aBox, theSR.IsSplittable());
|
|
}
|
|
//=======================================================================
|
|
//function : ForceInterfVE
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::ForceInterfVE(const Standard_Integer nV,
|
|
Handle(BOPDS_PaveBlock)& aPB,
|
|
TColStd_MapOfInteger& theMEdges)
|
|
{
|
|
Standard_Integer nE, nVx, nVSD, iFlag;
|
|
Standard_Real aT, aTolVNew;
|
|
//
|
|
nE = aPB->OriginalEdge();
|
|
//
|
|
const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
|
|
if (aSIE.HasSubShape(nV)) {
|
|
return Standard_True;
|
|
}
|
|
//
|
|
if (myDS->HasInterf(nV, nE)) {
|
|
return Standard_True;
|
|
}
|
|
//
|
|
if (myDS->HasInterfShapeSubShapes(nV, nE)) {
|
|
return Standard_True;
|
|
}
|
|
//
|
|
if (aPB->Pave1().Index() == nV ||
|
|
aPB->Pave2().Index() == nV) {
|
|
return Standard_True;
|
|
}
|
|
//
|
|
nVx = nV;
|
|
if (myDS->HasShapeSD(nV, nVSD)) {
|
|
nVx = nVSD;
|
|
}
|
|
//
|
|
const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nVx);
|
|
const TopoDS_Edge& aE = *(TopoDS_Edge*) &myDS->Shape(nE);
|
|
//
|
|
iFlag = myContext->ComputeVE(aV, aE, aT, aTolVNew, myFuzzyValue);
|
|
if (iFlag == 0 || iFlag == -4) {
|
|
BOPDS_Pave aPave;
|
|
//
|
|
//
|
|
BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE();
|
|
aVEs.SetIncrement(10);
|
|
// 1
|
|
BOPDS_InterfVE& aVE=aVEs.Appended();
|
|
aVE.SetIndices(nV, nE);
|
|
aVE.SetParameter(aT);
|
|
// 2
|
|
myDS->AddInterf(nV, nE);
|
|
//
|
|
// 3 update vertex V/E if necessary
|
|
nVx=UpdateVertex(nV, aTolVNew);
|
|
// 4
|
|
if (myDS->IsNewShape(nVx)) {
|
|
aVE.SetIndexNew(nVx);
|
|
}
|
|
// 5 append ext pave to pave block
|
|
aPave.SetIndex(nVx);
|
|
aPave.SetParameter(aT);
|
|
aPB->AppendExtPave(aPave);
|
|
//
|
|
theMEdges.Add(nE);
|
|
//
|
|
// check for self-interference
|
|
Standard_Integer iRV = myDS->Rank(nV);
|
|
if (iRV >= 0 && iRV == myDS->Rank(nE)) {
|
|
// add warning status
|
|
TopoDS_Compound aWC;
|
|
BRep_Builder().MakeCompound(aWC);
|
|
BRep_Builder().Add(aWC, aV);
|
|
BRep_Builder().Add(aWC, aE);
|
|
AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
|
|
}
|
|
return Standard_True;
|
|
}
|
|
return Standard_False;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetPBBox
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
|
|
const Handle(BOPDS_PaveBlock)& thePB,
|
|
BOPAlgo_DataMapOfPaveBlockBndBox& thePBBox,
|
|
Standard_Real& theFirst,
|
|
Standard_Real& theLast,
|
|
Standard_Real& theSFirst,
|
|
Standard_Real& theSLast,
|
|
Bnd_Box& theBox)
|
|
{
|
|
thePB->Range(theFirst, theLast);
|
|
// check the validity of PB's range
|
|
Standard_Boolean bValid = theLast - theFirst > Precision::PConfusion();
|
|
if (!bValid) {
|
|
return bValid;
|
|
}
|
|
//
|
|
// check shrunk data
|
|
if (thePB->HasShrunkData()) {
|
|
Standard_Boolean bIsSplittable;
|
|
thePB->ShrunkData(theSFirst, theSLast, theBox, bIsSplittable);
|
|
return bValid;
|
|
}
|
|
//
|
|
theSFirst = theFirst;
|
|
theSLast = theLast;
|
|
// check the map
|
|
if (thePBBox.IsBound(thePB)) {
|
|
theBox = thePBBox.Find(thePB);
|
|
}
|
|
else {
|
|
// build bounding box
|
|
BRepAdaptor_Curve aBAC(theE);
|
|
Standard_Real aTol = BRep_Tool::Tolerance(theE) + Precision::Confusion();
|
|
BndLib_Add3dCurve::Add(aBAC, theSFirst, theSLast, aTol, theBox);
|
|
thePBBox.Bind(thePB, theBox);
|
|
}
|
|
return bValid;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : UpdateVerticesOfCB
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::UpdateVerticesOfCB()
|
|
{
|
|
// Fence map to avoid checking same Common block twice
|
|
BOPDS_MapOfPaveBlock aMPBFence;
|
|
|
|
BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
|
|
const Standard_Integer aNbPBP = aPBP.Length();
|
|
for (Standard_Integer i = 0; i < aNbPBP; ++i)
|
|
{
|
|
const BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
|
|
BOPDS_ListIteratorOfListOfPaveBlock itPB(aLPB);
|
|
for (; itPB.More(); itPB.Next())
|
|
{
|
|
const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(itPB.Value());
|
|
if (aCB.IsNull())
|
|
continue;
|
|
|
|
const Handle(BOPDS_PaveBlock)& aPBR = aCB->PaveBlock1();
|
|
if (!aMPBFence.Add(aPBR))
|
|
continue;
|
|
|
|
Standard_Real aTolCB = aCB->Tolerance();
|
|
if (aTolCB > 0.)
|
|
{
|
|
UpdateVertex(aPBR->Pave1().Index(), aTolCB);
|
|
UpdateVertex(aPBR->Pave2().Index(), aTolCB);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ForceInterfEE
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPAlgo_PaveFiller::ForceInterfEE()
|
|
{
|
|
// Now that we have vertices increased and unified, try to find additional
|
|
// common blocks among the pairs of edges.
|
|
// Since all real intersections should have already happened, here we
|
|
// are interested in common blocks only, thus we need to check only
|
|
// those pairs of pave blocks with the same bounding vertices.
|
|
|
|
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
|
|
|
|
// Initialize pave blocks for all vertices which participated in intersections
|
|
const Standard_Integer aNbS = myDS->NbSourceShapes();
|
|
for (Standard_Integer i = 0; i < aNbS; ++i)
|
|
{
|
|
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
|
|
if (aSI.ShapeType() == TopAbs_VERTEX)
|
|
{
|
|
if (myDS->HasInterf(i))
|
|
myDS->InitPaveBlocksForVertex(i);
|
|
}
|
|
}
|
|
|
|
// Fill the connection map from bounding vertices to pave blocks
|
|
// having those bounding vertices
|
|
NCollection_IndexedDataMap<BOPDS_Pair,
|
|
BOPDS_ListOfPaveBlock,
|
|
BOPDS_PairMapHasher> aPBMap(1, anAlloc);
|
|
// Fence map of pave blocks
|
|
BOPDS_MapOfPaveBlock aMPBFence(1, anAlloc);
|
|
|
|
for (Standard_Integer i = 0; i < aNbS; ++i)
|
|
{
|
|
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
|
|
if (aSI.ShapeType() != TopAbs_EDGE)
|
|
// Not an edge
|
|
continue;
|
|
|
|
if (!aSI.HasReference())
|
|
// Edge has no pave blocks
|
|
continue;
|
|
|
|
if (aSI.HasFlag())
|
|
// Degenerated edge
|
|
continue;
|
|
|
|
const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(i);
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
|
|
for (; aItLPB.More(); aItLPB.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
|
|
const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
|
|
if (!aMPBFence.Add(aPBR))
|
|
continue;
|
|
|
|
// Get indices
|
|
Standard_Integer nV1, nV2;
|
|
aPBR->Indices(nV1, nV2);
|
|
|
|
// Add pave block to a map
|
|
BOPDS_Pair aPair(nV1, nV2);
|
|
BOPDS_ListOfPaveBlock *pList = aPBMap.ChangeSeek(aPair);
|
|
if (!pList)
|
|
pList = &aPBMap(aPBMap.Add(aPair, BOPDS_ListOfPaveBlock(anAlloc)));
|
|
pList->Append(aPBR);
|
|
}
|
|
}
|
|
|
|
Standard_Integer aNbPB = aPBMap.Extent();
|
|
if (!aNbPB)
|
|
return;
|
|
|
|
// Prepare pave blocks with the same vertices for intersection.
|
|
BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
|
|
|
|
for (Standard_Integer i = 1; i <= aNbPB; ++i)
|
|
{
|
|
const BOPDS_ListOfPaveBlock& aLPB = aPBMap(i);
|
|
if (aLPB.Extent() < 2)
|
|
continue;
|
|
|
|
const BOPDS_Pair& aPair = aPBMap.FindKey(i);
|
|
Standard_Integer nV1, nV2;
|
|
aPair.Indices(nV1, nV2);
|
|
|
|
const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
|
|
const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
|
|
|
|
// Use the max tolerance of vertices as Fuzzy value for intersection
|
|
// of edges
|
|
Standard_Real aTolAdd = 2 * Max(BRep_Tool::Tolerance(aV1),
|
|
BRep_Tool::Tolerance(aV2));
|
|
|
|
// All possible pairs combined from the list <aLPB> should be checked
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB1(aLPB);
|
|
for (; aItLPB1.More(); aItLPB1.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value();
|
|
const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPB1);
|
|
const Standard_Integer nE1 = aPB1->OriginalEdge();
|
|
const Standard_Integer iR1 = myDS->Rank(nE1);
|
|
const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1));
|
|
Standard_Real aT11, aT12;
|
|
aPB1->Range(aT11, aT12);
|
|
BRepAdaptor_Curve aBAC1(aE1);
|
|
gp_Pnt aPm;
|
|
gp_Vec aVTgt1;
|
|
aBAC1.D1((aT11 + aT12) * 0.5, aPm, aVTgt1);
|
|
if (aVTgt1.SquareMagnitude() < gp::Resolution())
|
|
continue;
|
|
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB2 = aItLPB1;
|
|
for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next())
|
|
{
|
|
const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value();
|
|
const Handle(BOPDS_CommonBlock)& aCB2 = myDS->CommonBlock(aPB2);
|
|
const Standard_Integer nE2 = aPB2->OriginalEdge();
|
|
const Standard_Integer iR2 = myDS->Rank(nE2);
|
|
|
|
// Check that the edges came from different arguments
|
|
if (iR1 == iR2)
|
|
{
|
|
// If the sharing of the vertices is not original, but has been acquired
|
|
// during the operation, check the coincidence of the edges even if
|
|
// they came from the same argument
|
|
if ((!myDS->IsNewShape(nV1) && (myDS->Rank(nV1) == iR1)) ||
|
|
(!myDS->IsNewShape(nV2) && (myDS->Rank(nV2) == iR2)))
|
|
continue;
|
|
}
|
|
|
|
// Check that the Pave blocks do not form the Common block already
|
|
if (!aCB1.IsNull() && !aCB2.IsNull())
|
|
{
|
|
if (aCB1 == aCB2)
|
|
continue;
|
|
}
|
|
|
|
const TopoDS_Edge& aE2 = TopoDS::Edge(myDS->Shape(nE2));
|
|
Standard_Real aT21, aT22;
|
|
aPB2->Range(aT21, aT22);
|
|
|
|
// Check the angle between edges in the middle point.
|
|
// If the angle is more than 10 degrees, do not use the additional
|
|
// tolerance, as it may lead to undesired unification of edges
|
|
Standard_Boolean bUseAddTol = Standard_True;
|
|
{
|
|
GeomAPI_ProjectPointOnCurve& aProjPC = myContext->ProjPC(aE2);
|
|
aProjPC.Perform(aPm);
|
|
if (!aProjPC.NbPoints())
|
|
continue;
|
|
|
|
BRepAdaptor_Curve aBAC2(aE2);
|
|
gp_Pnt aPm2;
|
|
gp_Vec aVTgt2;
|
|
aBAC2.D1(aProjPC.LowerDistanceParameter(), aPm2, aVTgt2);
|
|
if (aVTgt2.SquareMagnitude() < gp::Resolution())
|
|
continue;
|
|
// The angle should be close to zero
|
|
Standard_Real aCos = aVTgt1.Dot(aVTgt2);
|
|
if (Abs(aCos) < 0.984)
|
|
bUseAddTol = Standard_False;
|
|
}
|
|
|
|
// Add pair for intersection
|
|
BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge.Appended();
|
|
anEdgeEdge.UseQuickCoincidenceCheck(Standard_True);
|
|
anEdgeEdge.SetPaveBlock1(aPB1);
|
|
anEdgeEdge.SetPaveBlock2(aPB2);
|
|
anEdgeEdge.SetEdge1(aE1, aT11, aT12);
|
|
anEdgeEdge.SetEdge2(aE2, aT21, aT22);
|
|
if (bUseAddTol)
|
|
anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
|
|
else
|
|
anEdgeEdge.SetFuzzyValue(myFuzzyValue);
|
|
anEdgeEdge.SetProgressIndicator(myProgressIndicator);
|
|
}
|
|
}
|
|
}
|
|
|
|
Standard_Integer aNbPairs = aVEdgeEdge.Length();
|
|
if (!aNbPairs)
|
|
return;
|
|
|
|
aPBMap.Clear();
|
|
aMPBFence.Clear();
|
|
anAlloc->Reset();
|
|
|
|
// Perform intersection of the found pairs
|
|
BOPAlgo_EdgeEdgeCnt::Perform(myRunParallel, aVEdgeEdge);
|
|
|
|
BOPDS_VectorOfInterfEE& aEEs = myDS->InterfEE();
|
|
if (aEEs.IsEmpty())
|
|
aEEs.SetIncrement(10);
|
|
|
|
// Analyze the results of intersection looking for TopAbs_EDGE
|
|
// intersection type only.
|
|
|
|
BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock aMPBLPB(1, anAlloc);
|
|
|
|
for (Standard_Integer i = 0; i < aNbPairs; ++i)
|
|
{
|
|
BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge(i);
|
|
if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors())
|
|
{
|
|
// Warn about failed intersection of sub-shapes
|
|
const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
|
|
const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
|
|
AddIntersectionFailedWarning(aE1, aE2);
|
|
continue;
|
|
}
|
|
|
|
const IntTools_SequenceOfCommonPrts& aCParts = anEdgeEdge.CommonParts();
|
|
if (aCParts.Length() != 1)
|
|
continue;
|
|
|
|
const IntTools_CommonPrt& aCP = aCParts(1);
|
|
if (aCP.Type() != TopAbs_EDGE)
|
|
continue;
|
|
|
|
Handle(BOPDS_PaveBlock) aPB[] = {anEdgeEdge.PaveBlock1(), anEdgeEdge.PaveBlock2()};
|
|
const Standard_Integer nE1 = aPB[0]->OriginalEdge();
|
|
const Standard_Integer nE2 = aPB[1]->OriginalEdge();
|
|
|
|
if (myDS->Rank(nE1) == myDS->Rank(nE2))
|
|
{
|
|
// Add acquired self-interference warning
|
|
TopoDS_Compound aWC;
|
|
BRep_Builder().MakeCompound(aWC);
|
|
BRep_Builder().Add(aWC, myDS->Shape(nE1));
|
|
BRep_Builder().Add(aWC, myDS->Shape(nE2));
|
|
AddWarning(new BOPAlgo_AlertAcquiredSelfIntersection(aWC));
|
|
}
|
|
|
|
BOPDS_InterfEE& aEE = aEEs.Appended();
|
|
aEE.SetIndices(nE1, nE2);
|
|
aEE.SetCommonPart(aCP);
|
|
myDS->AddInterf(nE1, nE2);
|
|
|
|
// Fill map for common blocks creation
|
|
for (Standard_Integer j = 0; j < 2; ++j)
|
|
{
|
|
if (myDS->IsCommonBlock(aPB[j]))
|
|
{
|
|
const BOPDS_ListOfPaveBlock& aLPBCB = myDS->CommonBlock(aPB[j])->PaveBlocks();
|
|
BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPBCB);
|
|
for (; aItLPB.More(); aItLPB.Next())
|
|
BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock),
|
|
TColStd_MapTransientHasher>(aPB[j], aItLPB.Value(), aMPBLPB, anAlloc);
|
|
}
|
|
}
|
|
BOPAlgo_Tools::FillMap<Handle(BOPDS_PaveBlock),
|
|
TColStd_MapTransientHasher>(aPB[0], aPB[1], aMPBLPB, anAlloc);
|
|
}
|
|
|
|
// Create new common blocks of coinciding pairs.
|
|
BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, anAlloc, myDS);
|
|
}
|