Warning, file /include/opencascade/NCollection_UBTree.hxx was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef NCollection_UBTree_HeaderFile
0017 #define NCollection_UBTree_HeaderFile
0018
0019 #include <NCollection_BaseAllocator.hxx>
0020 #include <NCollection_DefineAlloc.hxx>
0021 #include <NCollection_LocalArray.hxx>
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 template <class TheObjType, class TheBndType>
0065 class NCollection_UBTree
0066 {
0067 public:
0068
0069 DEFINE_STANDARD_ALLOC
0070 DEFINE_NCOLLECTION_ALLOC
0071
0072 public:
0073
0074
0075
0076
0077
0078 class Selector
0079 {
0080 public:
0081
0082
0083
0084 Selector()
0085 : myStop(false)
0086 {
0087 }
0088
0089
0090
0091
0092
0093
0094 virtual bool Reject(const TheBndType&) const = 0;
0095
0096
0097
0098
0099
0100
0101
0102
0103 virtual bool Accept(const TheObjType&) = 0;
0104
0105
0106
0107
0108
0109
0110 bool Stop() const noexcept { return myStop; }
0111
0112
0113
0114
0115 virtual ~Selector() = default;
0116
0117 protected:
0118
0119
0120
0121
0122 bool myStop;
0123 };
0124
0125
0126
0127
0128
0129
0130
0131
0132 class TreeNode
0133 {
0134 public:
0135 DEFINE_STANDARD_ALLOC
0136 DEFINE_NCOLLECTION_ALLOC
0137
0138 public:
0139 TreeNode(const TheObjType& theObj, const TheBndType& theBnd)
0140 : myBnd(theBnd),
0141 myObject(theObj),
0142 myChildren(nullptr),
0143 myParent(nullptr)
0144 {
0145 }
0146
0147 bool IsLeaf() const noexcept { return !myChildren; }
0148
0149 bool IsRoot() const noexcept { return !myParent; }
0150
0151 const TheBndType& Bnd() const noexcept { return myBnd; }
0152
0153 TheBndType& ChangeBnd() noexcept { return myBnd; }
0154
0155 const TheObjType& Object() const noexcept { return myObject; }
0156
0157 const TreeNode& Child(const int i) const noexcept { return myChildren[i]; }
0158
0159 TreeNode& ChangeChild(const int i) noexcept { return myChildren[i]; }
0160
0161 const TreeNode& Parent() const noexcept { return *myParent; }
0162
0163 TreeNode& ChangeParent() noexcept { return *myParent; }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179 void Gemmate(const TheBndType& theNewBnd,
0180 const TheObjType& theObj,
0181 const TheBndType& theBnd,
0182 const occ::handle<NCollection_BaseAllocator>& theAlloc)
0183 {
0184 TreeNode* children = (TreeNode*)theAlloc->Allocate(2 * sizeof(TreeNode));
0185 new (&children[0]) TreeNode;
0186 new (&children[1]) TreeNode;
0187 children[0] = *this;
0188 children[1].myObject = theObj;
0189 children[1].myBnd = theBnd;
0190 children[0].myParent = children[1].myParent = this;
0191 if (!IsLeaf())
0192 {
0193 myChildren[0].myParent = children;
0194 myChildren[1].myParent = children;
0195 }
0196 myChildren = children;
0197 myBnd = theNewBnd;
0198 myObject = TheObjType();
0199 }
0200
0201
0202
0203
0204 void Kill(const int i, const occ::handle<NCollection_BaseAllocator>& theAlloc)
0205 {
0206 if (!IsLeaf())
0207 {
0208 TreeNode* oldChildren = myChildren;
0209 const int iopp = 1 - i;
0210 myBnd = oldChildren[iopp].myBnd;
0211 myObject = oldChildren[iopp].myObject;
0212 myChildren = oldChildren[iopp].myChildren;
0213 if (!IsLeaf())
0214 {
0215 myChildren[0].myParent = this;
0216 myChildren[1].myParent = this;
0217 }
0218 oldChildren[iopp].~TreeNode();
0219 delNode(&oldChildren[i], theAlloc);
0220 theAlloc->Free(oldChildren);
0221 }
0222 }
0223
0224 ~TreeNode() { myChildren = nullptr; }
0225
0226
0227
0228
0229 static void delNode(TreeNode* theNode, const occ::handle<NCollection_BaseAllocator>& theAlloc)
0230 {
0231 if (!theNode)
0232 return;
0233
0234
0235 constexpr int THE_INIT_STACK_SIZE = 64;
0236 NCollection_LocalArray<TreeNode*, THE_INIT_STACK_SIZE> aChildArrays(THE_INIT_STACK_SIZE);
0237 NCollection_LocalArray<TreeNode*, THE_INIT_STACK_SIZE> aStack(THE_INIT_STACK_SIZE);
0238 int aNumArrays = 0;
0239 int aTop = 0;
0240
0241 aStack[aTop++] = theNode;
0242
0243 while (aTop > 0)
0244 {
0245 TreeNode* aNode = aStack[--aTop];
0246 if (aNode->myChildren)
0247 {
0248
0249 if (aNumArrays >= static_cast<int>(aChildArrays.Size()))
0250 aChildArrays.Reallocate(aChildArrays.Size() * 2, true);
0251 aChildArrays[aNumArrays++] = aNode->myChildren;
0252
0253
0254 if (aTop + 2 > static_cast<int>(aStack.Size()))
0255 aStack.Reallocate(aStack.Size() * 2, true);
0256 aStack[aTop++] = &aNode->myChildren[1];
0257 aStack[aTop++] = &aNode->myChildren[0];
0258 }
0259 aNode->~TreeNode();
0260 }
0261
0262
0263 for (int i = 0; i < aNumArrays; ++i)
0264 theAlloc->Free(aChildArrays[i]);
0265 }
0266
0267 private:
0268 TreeNode()
0269 : myChildren(nullptr),
0270 myParent(nullptr)
0271 {
0272 }
0273
0274 TheBndType myBnd;
0275 TheObjType myObject;
0276 TreeNode* myChildren;
0277 TreeNode* myParent;
0278 };
0279
0280
0281
0282
0283
0284
0285 NCollection_UBTree()
0286 : myRoot(nullptr),
0287 myLastNode(nullptr),
0288 myAlloc(NCollection_BaseAllocator::CommonBaseAllocator())
0289 {
0290 }
0291
0292
0293
0294
0295 explicit NCollection_UBTree(const occ::handle<NCollection_BaseAllocator>& theAllocator)
0296 : myRoot(nullptr),
0297 myLastNode(nullptr),
0298 myAlloc(!theAllocator.IsNull() ? theAllocator
0299 : NCollection_BaseAllocator::CommonBaseAllocator())
0300 {
0301 }
0302
0303 NCollection_UBTree(NCollection_UBTree&& theOther) noexcept
0304 : myRoot(theOther.myRoot),
0305 myLastNode(theOther.myLastNode),
0306 myAlloc(std::move(theOther.myAlloc))
0307 {
0308 theOther.myRoot = nullptr;
0309 theOther.myLastNode = nullptr;
0310 }
0311
0312 NCollection_UBTree& operator=(NCollection_UBTree&& theOther) noexcept
0313 {
0314 if (this != &theOther)
0315 {
0316 Clear();
0317 myRoot = theOther.myRoot;
0318 myLastNode = theOther.myLastNode;
0319 myAlloc = std::move(theOther.myAlloc);
0320 theOther.myRoot = nullptr;
0321 theOther.myLastNode = nullptr;
0322 }
0323 return *this;
0324 }
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335 virtual bool Add(const TheObjType& theObj, const TheBndType& theBnd);
0336
0337
0338
0339
0340
0341
0342 virtual int Select(Selector& theSelector) const
0343 {
0344 return (IsEmpty() ? 0 : Select(Root(), theSelector));
0345 }
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 virtual void Clear(const occ::handle<NCollection_BaseAllocator>& aNewAlloc = nullptr)
0356 {
0357 if (myRoot)
0358 {
0359 TreeNode::delNode(myRoot, this->myAlloc);
0360 this->myAlloc->Free(myRoot);
0361 myRoot = nullptr;
0362 }
0363 if (!aNewAlloc.IsNull())
0364 myAlloc = aNewAlloc;
0365 }
0366
0367 bool IsEmpty() const noexcept { return !myRoot; }
0368
0369
0370
0371
0372
0373 const TreeNode& Root() const noexcept { return *myRoot; }
0374
0375
0376
0377
0378 virtual ~NCollection_UBTree() { Clear(); }
0379
0380
0381
0382
0383
0384
0385 const occ::handle<NCollection_BaseAllocator>& Allocator() const noexcept { return myAlloc; }
0386
0387 protected:
0388
0389
0390
0391
0392
0393
0394 TreeNode& ChangeLastNode() noexcept { return *myLastNode; }
0395
0396
0397
0398
0399
0400
0401 int Select(const TreeNode& theBranch, Selector& theSelector) const;
0402
0403 private:
0404
0405
0406
0407 NCollection_UBTree(const NCollection_UBTree&) = delete;
0408
0409
0410 NCollection_UBTree& operator=(const NCollection_UBTree&) = delete;
0411
0412
0413
0414 TreeNode* myRoot;
0415 TreeNode* myLastNode;
0416 occ::handle<NCollection_BaseAllocator> myAlloc;
0417 };
0418
0419
0420
0421 template <class TheObjType, class TheBndType>
0422 bool NCollection_UBTree<TheObjType, TheBndType>::Add(const TheObjType& theObj,
0423 const TheBndType& theBnd)
0424 {
0425 if (IsEmpty())
0426 {
0427
0428 myRoot = new (this->myAlloc) TreeNode(theObj, theBnd);
0429 myLastNode = myRoot;
0430 return true;
0431 }
0432
0433 TreeNode* pBranch = myRoot;
0434 bool isOutOfBranch = pBranch->Bnd().IsOut(theBnd);
0435
0436 for (;;)
0437 {
0438
0439 if (isOutOfBranch || pBranch->IsLeaf())
0440 {
0441 TheBndType aNewBnd = theBnd;
0442 aNewBnd.Add(pBranch->Bnd());
0443
0444 pBranch->Gemmate(aNewBnd, theObj, theBnd, this->myAlloc);
0445 myLastNode = &pBranch->ChangeChild(1);
0446 break;
0447 }
0448
0449
0450 pBranch->ChangeBnd().Add(theBnd);
0451
0452
0453
0454
0455 int iBest = 0;
0456 bool isOut[] = {pBranch->Child(0).Bnd().IsOut(theBnd), pBranch->Child(1).Bnd().IsOut(theBnd)};
0457 if (isOut[0] != isOut[1])
0458 iBest = (isOut[0] ? 1 : 0);
0459 else
0460 {
0461 TheBndType aUnion[] = {theBnd, theBnd};
0462 aUnion[0].Add(pBranch->Child(0).Bnd());
0463 aUnion[1].Add(pBranch->Child(1).Bnd());
0464 const double d1 = aUnion[0].SquareExtent();
0465 const double d2 = aUnion[1].SquareExtent();
0466 if (d1 > d2)
0467 iBest = 1;
0468 }
0469
0470
0471 isOutOfBranch = isOut[iBest];
0472 pBranch = &pBranch->ChangeChild(iBest);
0473 }
0474 return true;
0475 }
0476
0477
0478
0479 template <class TheObjType, class TheBndType>
0480 int NCollection_UBTree<TheObjType, TheBndType>::Select(const TreeNode& theBranch,
0481 Selector& theSelector) const
0482 {
0483
0484
0485 constexpr int THE_INIT_STACK_SIZE = 64;
0486 NCollection_LocalArray<const TreeNode*, THE_INIT_STACK_SIZE> aStack(THE_INIT_STACK_SIZE);
0487 int aTop = 0;
0488 int nSel = 0;
0489
0490 aStack[aTop++] = &theBranch;
0491
0492 while (aTop > 0)
0493 {
0494 const TreeNode* aNode = aStack[--aTop];
0495
0496 if (theSelector.Reject(aNode->Bnd()))
0497 continue;
0498
0499 if (aNode->IsLeaf())
0500 {
0501 if (theSelector.Accept(aNode->Object()))
0502 nSel++;
0503 if (theSelector.Stop())
0504 break;
0505 }
0506 else
0507 {
0508
0509 if (aTop + 2 > static_cast<int>(aStack.Size()))
0510 aStack.Reallocate(aStack.Size() * 2, true);
0511
0512 aStack[aTop++] = &aNode->Child(1);
0513 aStack[aTop++] = &aNode->Child(0);
0514 }
0515 }
0516 return nSel;
0517 }
0518
0519 #endif