mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
Switching the Boolean Operations algorithm to use the BVH tree instead of UB tree as selection of the elements from BVH tree is usually faster.
457 lines
14 KiB
C++
457 lines
14 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 <Bnd_OBB.hxx>
|
|
#include <Bnd_Tools.hxx>
|
|
#include <BOPDS_DS.hxx>
|
|
#include <BOPDS_IndexRange.hxx>
|
|
#include <BOPDS_Iterator.hxx>
|
|
#include <BOPDS_Pair.hxx>
|
|
#include <BOPDS_MapOfPair.hxx>
|
|
#include <BOPDS_Tools.hxx>
|
|
#include <BOPTools_BoxTree.hxx>
|
|
#include <BOPTools_Parallel.hxx>
|
|
#include <IntTools_Context.hxx>
|
|
#include <NCollection_Vector.hxx>
|
|
#include <TopoDS_Shape.hxx>
|
|
#include <algorithm>
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//=======================================================================
|
|
//class : BOPDS_TreeSelector
|
|
//purpose :
|
|
//=======================================================================
|
|
class BOPDS_TSR : public BOPTools_BoxTreeSelector
|
|
{
|
|
public:
|
|
BOPDS_TSR() :
|
|
BOPTools_BoxTreeSelector(),
|
|
myHasBRep(Standard_False),
|
|
myIndex(-1) {}
|
|
//
|
|
virtual ~BOPDS_TSR() {
|
|
}
|
|
//
|
|
void SetHasBRep(const Standard_Boolean bFlag) {
|
|
myHasBRep=bFlag;
|
|
}
|
|
//
|
|
void SetIndex(const Standard_Integer theIndex) { myIndex = theIndex; }
|
|
//
|
|
Standard_Integer Index() const { return myIndex; }
|
|
//
|
|
void Perform() {
|
|
if (myHasBRep) {
|
|
Select();
|
|
}
|
|
}
|
|
//
|
|
protected:
|
|
Standard_Boolean myHasBRep;
|
|
Standard_Integer myIndex;
|
|
};
|
|
//
|
|
//=======================================================================
|
|
typedef NCollection_Vector<BOPDS_TSR> BOPDS_VectorOfTSR;
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//=======================================================================
|
|
//function :
|
|
//purpose :
|
|
//=======================================================================
|
|
BOPDS_Iterator::BOPDS_Iterator()
|
|
:
|
|
myAllocator(NCollection_BaseAllocator::CommonBaseAllocator()),
|
|
myRunParallel(Standard_False),
|
|
myUseExt(Standard_False)
|
|
{
|
|
Standard_Integer i, aNb;
|
|
//
|
|
myDS=NULL;
|
|
myLength=0;
|
|
//
|
|
aNb=BOPDS_DS::NbInterfTypes();
|
|
myLists.SetIncrement(aNb);
|
|
for (i=0; i<aNb; ++i) {
|
|
myLists.Appended();
|
|
}
|
|
|
|
const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
|
|
myExtLists.SetIncrement(aNbExt);
|
|
for (i = 0; i < aNbExt; ++i) {
|
|
myExtLists.Appended();
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function :
|
|
//purpose :
|
|
//=======================================================================
|
|
BOPDS_Iterator::BOPDS_Iterator
|
|
(const Handle(NCollection_BaseAllocator)& theAllocator)
|
|
:
|
|
myAllocator(theAllocator),
|
|
myLists(0, theAllocator),
|
|
myRunParallel(Standard_False),
|
|
myExtLists(0, theAllocator),
|
|
myUseExt(Standard_False)
|
|
{
|
|
Standard_Integer i, aNb;
|
|
//
|
|
myDS=NULL;
|
|
myLength=0;
|
|
//
|
|
aNb=BOPDS_DS::NbInterfTypes();
|
|
myLists.SetIncrement(aNb);
|
|
for (i=0; i<aNb; ++i) {
|
|
myLists.Appended();
|
|
}
|
|
|
|
const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
|
|
myExtLists.SetIncrement(aNbExt);
|
|
for (i = 0; i < aNbExt; ++i) {
|
|
myExtLists.Appended();
|
|
}
|
|
}
|
|
//=======================================================================
|
|
//function : ~
|
|
//purpose :
|
|
//=======================================================================
|
|
BOPDS_Iterator::~BOPDS_Iterator()
|
|
{
|
|
}
|
|
//=======================================================================
|
|
//function : SetRunParallel
|
|
//purpose :
|
|
//=======================================================================
|
|
void BOPDS_Iterator::SetRunParallel(const Standard_Boolean theFlag)
|
|
{
|
|
myRunParallel=theFlag;
|
|
}
|
|
//=======================================================================
|
|
//function : RunParallel
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BOPDS_Iterator::RunParallel()const
|
|
{
|
|
return myRunParallel;
|
|
}
|
|
//=======================================================================
|
|
// function: SetDS
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::SetDS(const BOPDS_PDS& aDS)
|
|
{
|
|
myDS=aDS;
|
|
}
|
|
//=======================================================================
|
|
// function: DS
|
|
// purpose:
|
|
//=======================================================================
|
|
const BOPDS_DS& BOPDS_Iterator::DS()const
|
|
{
|
|
return *myDS;
|
|
}
|
|
//=======================================================================
|
|
// function: ExpectedLength
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer BOPDS_Iterator::ExpectedLength() const
|
|
{
|
|
return myLength;
|
|
}
|
|
//=======================================================================
|
|
// function: BlockLength
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Integer BOPDS_Iterator::BlockLength() const
|
|
{
|
|
Standard_Integer aNbIIs;
|
|
Standard_Real aCfPredict=.5;
|
|
|
|
aNbIIs=ExpectedLength();
|
|
|
|
if (aNbIIs<=1) {
|
|
return 1;
|
|
}
|
|
//
|
|
aNbIIs=(Standard_Integer) (aCfPredict*(Standard_Real)aNbIIs);
|
|
return aNbIIs;
|
|
}
|
|
//=======================================================================
|
|
// function: Initialize
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::Initialize(const TopAbs_ShapeEnum aType1,
|
|
const TopAbs_ShapeEnum aType2)
|
|
{
|
|
Standard_Integer iX;
|
|
//
|
|
myLength=0;
|
|
iX=BOPDS_Tools::TypeToInteger(aType1, aType2);
|
|
if (iX >= 0)
|
|
{
|
|
BOPDS_VectorOfPair& aPairs = (myUseExt && iX < BOPDS_Iterator::NbExtInterfs()) ?
|
|
myExtLists(iX) : myLists(iX);
|
|
// sort interfering pairs for constant order of intersection
|
|
std::stable_sort(aPairs.begin(), aPairs.end());
|
|
// initialize iterator to access the pairs
|
|
myIterator.Init(aPairs);
|
|
myLength = aPairs.Length();
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: More
|
|
// purpose:
|
|
//=======================================================================
|
|
Standard_Boolean BOPDS_Iterator::More()const
|
|
{
|
|
return myIterator.More();
|
|
}
|
|
//=======================================================================
|
|
// function: Next
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::Next()
|
|
{
|
|
myIterator.Next();
|
|
}
|
|
//=======================================================================
|
|
// function: Value
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::Value(Standard_Integer& theI1,
|
|
Standard_Integer& theI2) const
|
|
{
|
|
Standard_Integer iT1, iT2, n1, n2;
|
|
//
|
|
const BOPDS_Pair& aPair = myIterator.Value();
|
|
aPair.Indices(n1, n2);
|
|
//
|
|
iT1=(Standard_Integer)(myDS->ShapeInfo(n1).ShapeType());
|
|
iT2=(Standard_Integer)(myDS->ShapeInfo(n2).ShapeType());
|
|
//
|
|
theI1=n1;
|
|
theI2=n2;
|
|
if (iT1<iT2) {
|
|
theI1=n2;
|
|
theI2=n1;
|
|
}
|
|
}
|
|
//=======================================================================
|
|
// function: Prepare
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::Prepare(const Handle(IntTools_Context)& theCtx,
|
|
const Standard_Boolean theCheckOBB,
|
|
const Standard_Real theFuzzyValue)
|
|
{
|
|
Standard_Integer i, aNbInterfTypes;
|
|
//
|
|
aNbInterfTypes=BOPDS_DS::NbInterfTypes();
|
|
myLength=0;
|
|
for (i=0; i<aNbInterfTypes; ++i) {
|
|
myLists(i).Clear();
|
|
}
|
|
//
|
|
if (myDS==NULL){
|
|
return;
|
|
}
|
|
Intersect(theCtx, theCheckOBB, theFuzzyValue);
|
|
}
|
|
//
|
|
//=======================================================================
|
|
// function: Intersect
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
|
|
const Standard_Boolean theCheckOBB,
|
|
const Standard_Real theFuzzyValue)
|
|
{
|
|
const Standard_Integer aNb = myDS->NbSourceShapes();
|
|
|
|
// Prepare BVH
|
|
BOPTools_BoxTree aBoxTree;
|
|
aBoxTree.SetSize (aNb);
|
|
for (Standard_Integer i = 0; i < aNb; ++i)
|
|
{
|
|
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
|
|
if (!aSI.HasBRep())
|
|
continue;
|
|
const Bnd_Box& aBox = aSI.Box();
|
|
aBoxTree.Add (i, Bnd_Tools::Bnd2BVH (aBox));
|
|
}
|
|
|
|
// Build BVH
|
|
aBoxTree.Build();
|
|
|
|
// Select pairs of shapes with interfering bounding boxes
|
|
BOPTools_BoxPairSelector aPairSelector;
|
|
aPairSelector.SetBVHSets (&aBoxTree, &aBoxTree);
|
|
aPairSelector.SetSame (Standard_True);
|
|
aPairSelector.Select();
|
|
aPairSelector.Sort();
|
|
|
|
// Treat the selected pairs
|
|
const std::vector<BOPTools_BoxPairSelector::PairIDs>& aPairs = aPairSelector.Pairs();
|
|
const Standard_Integer aNbPairs = static_cast<Standard_Integer> (aPairs.size());
|
|
|
|
Standard_Integer iPair = 0;
|
|
|
|
const Standard_Integer aNbR = myDS->NbRanges();
|
|
for (Standard_Integer iR = 0; iR < aNbR; ++iR)
|
|
{
|
|
const BOPDS_IndexRange& aRange = myDS->Range(iR);
|
|
|
|
for (; iPair < aNbPairs; ++iPair)
|
|
{
|
|
const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair];
|
|
if (!aRange.Contains (aPair.ID1))
|
|
// Go to the next range
|
|
break;
|
|
|
|
if (aRange.Contains (aPair.ID2))
|
|
// Go to the next pair
|
|
continue;
|
|
|
|
const BOPDS_ShapeInfo& aSI1 = myDS->ShapeInfo (aPair.ID1);
|
|
const BOPDS_ShapeInfo& aSI2 = myDS->ShapeInfo (aPair.ID2);
|
|
|
|
const TopAbs_ShapeEnum aType1 = aSI1.ShapeType();
|
|
const TopAbs_ShapeEnum aType2 = aSI2.ShapeType();
|
|
|
|
Standard_Integer iType1 = BOPDS_Tools::TypeToInteger (aType1);
|
|
Standard_Integer iType2 = BOPDS_Tools::TypeToInteger (aType2);
|
|
|
|
// avoid interfering of the shape with its sub-shapes
|
|
if (((iType1 < iType2) && aSI1.HasSubShape (aPair.ID2)) ||
|
|
((iType1 > iType2) && aSI2.HasSubShape (aPair.ID1)))
|
|
continue;
|
|
|
|
if (theCheckOBB)
|
|
{
|
|
// Check intersection of Oriented bounding boxes of the shapes
|
|
const Bnd_OBB& anOBB1 = theCtx->OBB (aSI1.Shape(), theFuzzyValue);
|
|
const Bnd_OBB& anOBB2 = theCtx->OBB (aSI2.Shape(), theFuzzyValue);
|
|
|
|
if (anOBB1.IsOut (anOBB2))
|
|
continue;
|
|
}
|
|
|
|
Standard_Integer iX = BOPDS_Tools::TypeToInteger (aType1, aType2);
|
|
myLists(iX).Append (BOPDS_Pair (Min (aPair.ID1, aPair.ID2),
|
|
Max (aPair.ID1, aPair.ID2)));
|
|
}
|
|
}
|
|
}
|
|
|
|
//=======================================================================
|
|
// function: IntersectExt
|
|
// purpose:
|
|
//=======================================================================
|
|
void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices)
|
|
{
|
|
if (!myDS)
|
|
return;
|
|
|
|
const Standard_Integer aNb = myDS->NbSourceShapes();
|
|
|
|
BOPTools_BoxTree aBoxTree;
|
|
aBoxTree.SetSize (aNb);
|
|
BOPDS_VectorOfTSR aVTSR(theIndices.Extent());
|
|
//
|
|
for (Standard_Integer i = 0; i < aNb; ++i)
|
|
{
|
|
const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
|
|
if (!aSI.IsInterfering() || (aSI.ShapeType() == TopAbs_SOLID))
|
|
continue;
|
|
//
|
|
if (theIndices.Contains (i))
|
|
{
|
|
Standard_Integer nVSD = i;
|
|
myDS->HasShapeSD (i, nVSD);
|
|
const BOPDS_ShapeInfo& aSISD = myDS->ShapeInfo (nVSD);
|
|
const Bnd_Box& aBox = aSISD.Box ();
|
|
aBoxTree.Add (i, Bnd_Tools::Bnd2BVH(aBox));
|
|
|
|
BOPDS_TSR& aTSR=aVTSR.Appended();
|
|
aTSR.SetHasBRep(Standard_True);
|
|
aTSR.SetBVHSet (&aBoxTree);
|
|
aTSR.SetBox (Bnd_Tools::Bnd2BVH (aBox));
|
|
aTSR.SetIndex (i);
|
|
}
|
|
else
|
|
{
|
|
aBoxTree.Add (i, Bnd_Tools::Bnd2BVH (aSI.Box ()));
|
|
}
|
|
}
|
|
|
|
aBoxTree.Build();
|
|
|
|
// Perform selection
|
|
BOPTools_Parallel::Perform (myRunParallel, aVTSR);
|
|
|
|
// Treat selections
|
|
|
|
// Fence map to avoid duplicating pairs
|
|
BOPDS_MapOfPair aMPFence;
|
|
|
|
const Standard_Integer aNbV = aVTSR.Length();
|
|
for (Standard_Integer k = 0; k < aNbV; ++k)
|
|
{
|
|
BOPDS_TSR& aTSRi = aVTSR(k);
|
|
const TColStd_ListOfInteger& aLI = aTSRi.Indices();
|
|
if (aLI.IsEmpty())
|
|
continue;
|
|
|
|
const Standard_Integer i = aTSRi.Index();
|
|
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
|
|
const Standard_Integer iRankI = myDS->Rank(i);
|
|
const TopAbs_ShapeEnum aTI = aSI.ShapeType();
|
|
const Standard_Integer iTI = BOPDS_Tools::TypeToInteger(aTI);
|
|
|
|
TColStd_ListIteratorOfListOfInteger itLI(aLI);
|
|
for (; itLI.More(); itLI.Next())
|
|
{
|
|
const Standard_Integer j = itLI.Value(); // Index in DS
|
|
const Standard_Integer iRankJ = myDS->Rank(j);
|
|
if (iRankI == iRankJ)
|
|
continue;
|
|
|
|
const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j);
|
|
const TopAbs_ShapeEnum aTJ = aSJ.ShapeType();
|
|
const Standard_Integer iTJ = BOPDS_Tools::TypeToInteger(aTJ);
|
|
|
|
// avoid interfering of the shape with its sub-shapes
|
|
if (((iTI < iTJ) && aSI.HasSubShape(j)) ||
|
|
((iTI > iTJ) && aSJ.HasSubShape(i)))
|
|
continue;
|
|
|
|
BOPDS_Pair aPair(i, j);
|
|
if (aMPFence.Add(aPair))
|
|
{
|
|
const Standard_Integer iX = BOPDS_Tools::TypeToInteger(aTI, aTJ);
|
|
if (iX < BOPDS_Iterator::NbExtInterfs())
|
|
myExtLists(iX).Append(aPair);
|
|
}
|
|
}
|
|
}
|
|
|
|
myUseExt = Standard_True;
|
|
}
|