File indexing completed on 2026-09-16 09:17:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef NCollection_CellFilter_HeaderFile
0017 #define NCollection_CellFilter_HeaderFile
0018
0019 #include <NCollection_LocalArray.hxx>
0020 #include <NCollection_Array1.hxx>
0021 #include <Standard_HashUtils.hxx>
0022 #include <NCollection_Map.hxx>
0023 #include <NCollection_IncAllocator.hxx>
0024
0025
0026 enum NCollection_CellFilter_Action
0027 {
0028 CellFilter_Keep = 0,
0029 CellFilter_Purge = 1
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
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 template <class Inspector>
0113 class NCollection_CellFilter
0114 {
0115 public:
0116 typedef typename Inspector::Target Target;
0117 typedef typename Inspector::Point Point;
0118
0119 public:
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 NCollection_CellFilter(const int theDim,
0131 const double theCellSize = 0,
0132 const occ::handle<NCollection_IncAllocator>& theAlloc = nullptr)
0133 : myCellSize(0, theDim - 1)
0134 {
0135 myDim = theDim;
0136 Reset(theCellSize, theAlloc);
0137 }
0138
0139
0140 NCollection_CellFilter(const double theCellSize = 0,
0141 const occ::handle<NCollection_IncAllocator>& theAlloc = nullptr)
0142 : myCellSize(0, Inspector::Dimension - 1)
0143 {
0144 myDim = Inspector::Dimension;
0145 Reset(theCellSize, theAlloc);
0146 }
0147
0148
0149 void Reset(double theCellSize, const occ::handle<NCollection_IncAllocator>& theAlloc = nullptr)
0150 {
0151 for (int i = 0; i < myDim; i++)
0152 myCellSize(i) = theCellSize;
0153 resetAllocator(theAlloc);
0154 }
0155
0156
0157 void Reset(NCollection_Array1<double>& theCellSize,
0158 const occ::handle<NCollection_IncAllocator>& theAlloc = nullptr)
0159 {
0160 myCellSize = theCellSize;
0161 resetAllocator(theAlloc);
0162 }
0163
0164
0165 void Add(const Target& theTarget, const Point& thePnt)
0166 {
0167 Cell aCell(thePnt, myCellSize);
0168 add(aCell.index, theTarget);
0169 }
0170
0171
0172
0173
0174 void Add(const Target& theTarget, const Point& thePntMin, const Point& thePntMax)
0175 {
0176
0177 Cell aCellMin(thePntMin, myCellSize);
0178 Cell aCellMax(thePntMax, myCellSize);
0179 Cell aCell(aCellMin.index);
0180
0181 iterateAdd(myDim - 1, aCell.index, aCellMin, aCellMax, theTarget);
0182 }
0183
0184
0185
0186 void Remove(const Target& theTarget, const Point& thePnt)
0187 {
0188 Cell aCell(thePnt, myCellSize);
0189 remove(aCell, theTarget);
0190 }
0191
0192
0193
0194
0195
0196
0197 void Remove(const Target& theTarget, const Point& thePntMin, const Point& thePntMax)
0198 {
0199
0200 Cell aCellMin(thePntMin, myCellSize);
0201 Cell aCellMax(thePntMax, myCellSize);
0202 Cell aCell(aCellMin.index);
0203
0204 iterateRemove(myDim - 1, aCell, aCellMin, aCellMax, theTarget);
0205 }
0206
0207
0208 void Inspect(const Point& thePnt, Inspector& theInspector)
0209 {
0210 Cell aCell(thePnt, myCellSize);
0211 inspect(aCell, theInspector);
0212 }
0213
0214
0215
0216
0217 void Inspect(const Point& thePntMin, const Point& thePntMax, Inspector& theInspector)
0218 {
0219
0220 Cell aCellMin(thePntMin, myCellSize);
0221 Cell aCellMax(thePntMax, myCellSize);
0222 Cell aCell(aCellMin.index);
0223
0224 iterateInspect(myDim - 1, aCell, aCellMin, aCellMax, theInspector);
0225 }
0226
0227 protected:
0228
0229
0230
0231 struct ListNode
0232 {
0233 ListNode() = delete;
0234
0235 Target Object;
0236 ListNode* Next;
0237 };
0238
0239
0240 typedef int Cell_IndexType;
0241 typedef NCollection_LocalArray<Cell_IndexType, 10> CellIndex;
0242
0243
0244
0245
0246
0247
0248 struct Cell
0249 {
0250 public:
0251
0252 Cell(const Point& thePnt, const NCollection_Array1<double>& theCellSize)
0253 : index(theCellSize.Length()),
0254 Objects(nullptr)
0255 {
0256 for (int i = 0; i < theCellSize.Length(); i++)
0257 {
0258 double aVal = (double)(Inspector::Coord(i, thePnt) / theCellSize(theCellSize.Lower() + i));
0259
0260
0261
0262
0263 index[i] = Cell_IndexType((aVal > INT_MAX - 1) ? fmod(aVal, (double)INT_MAX)
0264 : (aVal < INT_MIN + 1) ? fmod(aVal, (double)INT_MIN)
0265 : aVal);
0266 }
0267 }
0268
0269
0270 Cell(const CellIndex& theIndex)
0271 : index(theIndex.Size()),
0272 Objects(nullptr)
0273 {
0274 std::memcpy(index, theIndex, theIndex.Size() * sizeof(Cell_IndexType));
0275 }
0276
0277
0278 Cell(Cell&& theOther) noexcept
0279 : index(std::move(theOther.index)),
0280 Objects(theOther.Objects)
0281 {
0282 theOther.Objects = nullptr;
0283 }
0284
0285 Cell& operator=(Cell&& theOther) noexcept
0286 {
0287 index = std::move(theOther.index);
0288 Objects = theOther.Objects;
0289 theOther.Objects = nullptr;
0290 return *this;
0291 }
0292
0293
0294 ~Cell()
0295 {
0296 for (ListNode* aNode = Objects; aNode; aNode = aNode->Next)
0297 aNode->Object.~Target();
0298
0299 Objects = nullptr;
0300 }
0301
0302
0303 bool IsEqual(const Cell& theOther) const noexcept
0304 {
0305 const size_t aDim = index.Size();
0306 if (aDim != theOther.index.Size())
0307 return false;
0308 for (size_t i = 0; i < aDim; i++)
0309 if (index[i] != theOther.index[i])
0310 return false;
0311 return true;
0312 }
0313
0314 bool operator==(const Cell& theOther) const noexcept { return IsEqual(theOther); }
0315
0316 public:
0317 CellIndex index;
0318 ListNode* Objects;
0319 };
0320
0321 struct CellHasher
0322 {
0323 size_t operator()(const Cell& theCell) const noexcept
0324 {
0325 const std::size_t aDim = theCell.index.Size();
0326 return opencascade::hashBytes(&theCell.index[0],
0327 static_cast<int>(aDim * sizeof(Cell_IndexType)));
0328 }
0329
0330 bool operator()(const Cell& theCell1, const Cell& theCell2) const noexcept
0331 {
0332 return theCell1 == theCell2;
0333 }
0334 };
0335
0336 typedef NCollection_Map<Cell, CellHasher> CellMap;
0337
0338 protected:
0339
0340 void resetAllocator(const occ::handle<NCollection_IncAllocator>& theAlloc)
0341 {
0342 if (theAlloc.IsNull())
0343 myAllocator = new NCollection_IncAllocator;
0344 else
0345 myAllocator = theAlloc;
0346 myCells.Clear(myAllocator);
0347 }
0348
0349
0350 void add(const CellIndex& theIndex, const Target& theTarget)
0351 {
0352
0353 Cell& aMapCell = const_cast<Cell&>(myCells.TryEmplaced(theIndex));
0354
0355
0356 ListNode* aNode = (ListNode*)myAllocator->Allocate(sizeof(ListNode));
0357 new (&aNode->Object) Target(theTarget);
0358 aNode->Next = aMapCell.Objects;
0359 aMapCell.Objects = aNode;
0360 }
0361
0362
0363
0364 void iterateAdd(int idim,
0365 CellIndex& theIndex,
0366 const Cell& theMinIndex,
0367 const Cell& theMaxIndex,
0368 const Target& theTarget)
0369 {
0370 const Cell_IndexType aStart = theMinIndex.index[idim];
0371 const Cell_IndexType anEnd = theMaxIndex.index[idim];
0372 for (Cell_IndexType i = aStart; i <= anEnd; ++i)
0373 {
0374 theIndex[idim] = i;
0375 if (idim)
0376 {
0377 iterateAdd(idim - 1, theIndex, theMinIndex, theMaxIndex, theTarget);
0378 }
0379 else
0380 {
0381 add(theIndex, theTarget);
0382 }
0383 }
0384 }
0385
0386
0387 void remove(const Cell& theCell, const Target& theTarget)
0388 {
0389
0390 auto aMapCellOpt = myCells.Contained(theCell);
0391 if (!aMapCellOpt)
0392 return;
0393
0394 Cell& aMapCell = const_cast<Cell&>(aMapCellOpt->get());
0395
0396
0397 ListNode* aNode = aMapCell.Objects;
0398 ListNode* aPrev = nullptr;
0399 while (aNode)
0400 {
0401 ListNode* aNext = aNode->Next;
0402 if (Inspector::IsEqual(aNode->Object, theTarget))
0403 {
0404 aNode->Object.~Target();
0405 (aPrev ? aPrev->Next : aMapCell.Objects) = aNext;
0406
0407 }
0408 else
0409 aPrev = aNode;
0410 aNode = aNext;
0411 }
0412
0413
0414 if (!aMapCell.Objects)
0415 myCells.Remove(theCell);
0416 }
0417
0418
0419
0420 void iterateRemove(int idim,
0421 Cell& theCell,
0422 const Cell& theCellMin,
0423 const Cell& theCellMax,
0424 const Target& theTarget)
0425 {
0426 const Cell_IndexType aStart = theCellMin.index[idim];
0427 const Cell_IndexType anEnd = theCellMax.index[idim];
0428 for (Cell_IndexType i = aStart; i <= anEnd; ++i)
0429 {
0430 theCell.index[idim] = i;
0431 if (idim)
0432 {
0433 iterateRemove(idim - 1, theCell, theCellMin, theCellMax, theTarget);
0434 }
0435 else
0436 {
0437 remove(theCell, theTarget);
0438 }
0439 }
0440 }
0441
0442
0443 void inspect(const Cell& theCell, Inspector& theInspector)
0444 {
0445
0446 auto aMapCellOpt = myCells.Contained(theCell);
0447 if (!aMapCellOpt)
0448 return;
0449
0450 Cell& aMapCell = const_cast<Cell&>(aMapCellOpt->get());
0451
0452
0453 ListNode* aNode = aMapCell.Objects;
0454 ListNode* aPrev = nullptr;
0455 while (aNode)
0456 {
0457 ListNode* aNext = aNode->Next;
0458 NCollection_CellFilter_Action anAction = theInspector.Inspect(aNode->Object);
0459
0460 if (anAction == CellFilter_Purge)
0461 {
0462 aNode->Object.~Target();
0463 (aPrev ? aPrev->Next : aMapCell.Objects) = aNext;
0464
0465 }
0466 else
0467 aPrev = aNode;
0468 aNode = aNext;
0469 }
0470
0471
0472 if (!aMapCell.Objects)
0473 myCells.Remove(theCell);
0474 }
0475
0476
0477 void iterateInspect(int idim,
0478 Cell& theCell,
0479 const Cell& theCellMin,
0480 const Cell& theCellMax,
0481 Inspector& theInspector)
0482 {
0483 const Cell_IndexType aStart = theCellMin.index[idim];
0484 const Cell_IndexType anEnd = theCellMax.index[idim];
0485 for (Cell_IndexType i = aStart; i <= anEnd; ++i)
0486 {
0487 theCell.index[idim] = i;
0488 if (idim)
0489 {
0490 iterateInspect(idim - 1, theCell, theCellMin, theCellMax, theInspector);
0491 }
0492 else
0493 {
0494 inspect(theCell, theInspector);
0495 }
0496 }
0497 }
0498
0499 protected:
0500 int myDim;
0501 occ::handle<NCollection_BaseAllocator> myAllocator;
0502 CellMap myCells;
0503 NCollection_Array1<double> myCellSize;
0504 };
0505
0506 #endif