1
/***************************************************************************
2
* Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
25
#include "PointsGrid.h"
28
using namespace Points;
30
PointsGrid::PointsGrid(const PointKernel& rclM)
43
PointsGrid::RebuildGrid();
46
PointsGrid::PointsGrid()
49
, _ulCtGridsX(POINTS_CT_GRID)
50
, _ulCtGridsY(POINTS_CT_GRID)
51
, _ulCtGridsZ(POINTS_CT_GRID)
60
PointsGrid::PointsGrid(const PointKernel& rclM,
76
PointsGrid::Rebuild(ulX, ulY, ulZ);
79
PointsGrid::PointsGrid(const PointKernel& rclM, int iCtGridPerAxis)
92
PointsGrid::Rebuild(iCtGridPerAxis);
95
PointsGrid::PointsGrid(const PointKernel& rclM, double fGridLen)
108
Base::BoundBox3d clBBPts; // = _pclPoints->GetBoundBox();
109
for (const auto& pnt : *_pclPoints) {
112
PointsGrid::Rebuild(std::max<unsigned long>((unsigned long)(clBBPts.LengthX() / fGridLen), 1),
113
std::max<unsigned long>((unsigned long)(clBBPts.LengthY() / fGridLen), 1),
114
std::max<unsigned long>((unsigned long)(clBBPts.LengthZ() / fGridLen), 1));
117
void PointsGrid::Attach(const PointKernel& rclM)
123
void PointsGrid::Clear()
126
_pclPoints = nullptr;
129
void PointsGrid::Rebuild(unsigned long ulX, unsigned long ulY, unsigned long ulZ)
134
_ulCtElements = HasElements();
138
void PointsGrid::Rebuild(unsigned long ulPerGrid, unsigned long ulMaxGrid)
140
_ulCtElements = HasElements();
141
CalculateGridLength(ulPerGrid, ulMaxGrid);
145
void PointsGrid::Rebuild(int iCtGridPerAxis)
147
_ulCtElements = HasElements();
148
CalculateGridLength(iCtGridPerAxis);
152
void PointsGrid::InitGrid()
156
// Calculate grid lengths if not initialized
158
if ((_ulCtGridsX == 0) || (_ulCtGridsY == 0) || (_ulCtGridsZ == 0)) {
159
CalculateGridLength(POINTS_CT_GRID, POINTS_MAX_GRIDS);
162
// Determine the grid length and offset
165
Base::BoundBox3d clBBPts; // = _pclPoints->GetBoundBox();
166
for (const auto& pnt : *_pclPoints) {
170
double fLengthX = clBBPts.LengthX();
171
double fLengthY = clBBPts.LengthY();
172
double fLengthZ = clBBPts.LengthZ();
177
unsigned long num = _ulCtGridsX;
181
_fGridLenX = (1.0F + fLengthX) / double(num);
182
_fMinX = clBBPts.MinX - 0.5F;
186
unsigned long num = _ulCtGridsY;
190
_fGridLenY = (1.0F + fLengthY) / double(num);
191
_fMinY = clBBPts.MinY - 0.5F;
195
unsigned long num = _ulCtGridsZ;
199
_fGridLenZ = (1.0F + fLengthZ) / double(num);
200
_fMinZ = clBBPts.MinZ - 0.5F;
204
// Create data structure
206
_aulGrid.resize(_ulCtGridsX);
207
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
208
_aulGrid[i].resize(_ulCtGridsY);
209
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
210
_aulGrid[i][j].resize(_ulCtGridsZ);
215
unsigned long PointsGrid::InSide(const Base::BoundBox3d& rclBB,
216
std::vector<unsigned long>& raulElements,
217
bool bDelDoubles) const
219
unsigned long ulMinX {};
220
unsigned long ulMinY {};
221
unsigned long ulMinZ {};
222
unsigned long ulMaxX {};
223
unsigned long ulMaxY {};
224
unsigned long ulMaxZ {};
226
raulElements.clear();
228
// Grid boxes for a more detailed selection
229
Position(Base::Vector3d(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
230
Position(Base::Vector3d(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
232
for (auto i = ulMinX; i <= ulMaxX; i++) {
233
for (auto j = ulMinY; j <= ulMaxY; j++) {
234
for (auto k = ulMinZ; k <= ulMaxZ; k++) {
235
raulElements.insert(raulElements.end(),
236
_aulGrid[i][j][k].begin(),
237
_aulGrid[i][j][k].end());
243
// remove duplicate mentions
244
std::sort(raulElements.begin(), raulElements.end());
245
raulElements.erase(std::unique(raulElements.begin(), raulElements.end()),
249
return raulElements.size();
252
unsigned long PointsGrid::InSide(const Base::BoundBox3d& rclBB,
253
std::vector<unsigned long>& raulElements,
254
const Base::Vector3d& rclOrg,
256
bool bDelDoubles) const
258
unsigned long ulMinX {}, ulMinY {}, ulMinZ {};
259
unsigned long ulMaxX {}, ulMaxY {}, ulMaxZ {};
260
double fGridDiag = GetBoundBox(0, 0, 0).CalcDiagonalLength();
261
double fMinDistP2 = (fGridDiag * fGridDiag) + (fMaxDist * fMaxDist);
263
raulElements.clear();
265
// Grid boxes for a more detailed selection
266
Position(Base::Vector3d(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
267
Position(Base::Vector3d(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
269
for (auto i = ulMinX; i <= ulMaxX; i++) {
270
for (auto j = ulMinY; j <= ulMaxY; j++) {
271
for (auto k = ulMinZ; k <= ulMaxZ; k++) {
272
if (Base::DistanceP2(GetBoundBox(i, j, k).GetCenter(), rclOrg) < fMinDistP2) {
273
raulElements.insert(raulElements.end(),
274
_aulGrid[i][j][k].begin(),
275
_aulGrid[i][j][k].end());
282
// remove duplicate mentions
283
std::sort(raulElements.begin(), raulElements.end());
284
raulElements.erase(std::unique(raulElements.begin(), raulElements.end()),
288
return raulElements.size();
291
unsigned long PointsGrid::InSide(const Base::BoundBox3d& rclBB,
292
std::set<unsigned long>& raulElements) const
294
unsigned long ulMinX {}, ulMinY {}, ulMinZ {};
295
unsigned long ulMaxX {}, ulMaxY {}, ulMaxZ {};
297
raulElements.clear();
299
// Grid boxes for a more detailed selection
300
Position(Base::Vector3d(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
301
Position(Base::Vector3d(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
303
for (auto i = ulMinX; i <= ulMaxX; i++) {
304
for (auto j = ulMinY; j <= ulMaxY; j++) {
305
for (auto k = ulMinZ; k <= ulMaxZ; k++) {
306
raulElements.insert(_aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
311
return raulElements.size();
314
void PointsGrid::Position(const Base::Vector3d& rclPoint,
317
unsigned long& rulZ) const
319
if (rclPoint.x <= _fMinX) {
323
rulX = std::min<unsigned long>((unsigned long)((rclPoint.x - _fMinX) / _fGridLenX),
327
if (rclPoint.y <= _fMinY) {
331
rulY = std::min<unsigned long>((unsigned long)((rclPoint.y - _fMinY) / _fGridLenY),
335
if (rclPoint.z <= _fMinZ) {
339
rulZ = std::min<unsigned long>((unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ),
344
void PointsGrid::CalculateGridLength(unsigned long ulCtGrid, unsigned long ulMaxGrids)
346
// Calculate grid lengths or number of grids per dimension
347
// There should be about 10 (?!?!) facets per grid
348
// or max grids should not exceed 10000
349
Base::BoundBox3d clBBPtsEnlarged; // = _pclPoints->GetBoundBox();
350
for (const auto& pnt : *_pclPoints) {
351
clBBPtsEnlarged.Add(pnt);
355
if (_ulCtElements > (ulMaxGrids * ulCtGrid)) {
357
(clBBPtsEnlarged.LengthX() * clBBPtsEnlarged.LengthY() * clBBPtsEnlarged.LengthZ())
358
/ float(ulMaxGrids * ulCtGrid);
362
(clBBPtsEnlarged.LengthX() * clBBPtsEnlarged.LengthY() * clBBPtsEnlarged.LengthZ())
363
/ float(_ulCtElements);
366
double fVol = fVolElem * float(ulCtGrid);
367
double fGridLen = float(pow((float)fVol, 1.0F / 3.0F));
371
std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthX() / fGridLen), 1);
373
std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthY() / fGridLen), 1);
375
std::max<unsigned long>((unsigned long)(clBBPtsEnlarged.LengthZ() / fGridLen), 1);
385
void PointsGrid::CalculateGridLength(int iCtGridPerAxis)
387
if (iCtGridPerAxis <= 0) {
388
CalculateGridLength(POINTS_CT_GRID, POINTS_MAX_GRIDS);
392
// Calculate grid lengths or number of grids per dimension
393
// There should be about 10 (?!?!) facets per grid
394
// or max grids should not exceed 10000
395
Base::BoundBox3d clBBPts; // = _pclPoints->GetBoundBox();
396
for (const auto& pnt : *_pclPoints) {
400
double fLenghtX = clBBPts.LengthX();
401
double fLenghtY = clBBPts.LengthY();
402
double fLenghtZ = clBBPts.LengthZ();
404
double fLenghtD = clBBPts.CalcDiagonalLength();
406
double fLengthTol = 0.05F * fLenghtD;
408
bool bLenghtXisZero = (fLenghtX <= fLengthTol);
409
bool bLenghtYisZero = (fLenghtY <= fLengthTol);
410
bool bLenghtZisZero = (fLenghtZ <= fLengthTol);
416
if (bLenghtXisZero) {
420
iMaxGrids *= iCtGridPerAxis;
423
if (bLenghtYisZero) {
427
iMaxGrids *= iCtGridPerAxis;
430
if (bLenghtZisZero) {
434
iMaxGrids *= iCtGridPerAxis;
437
unsigned long ulGridsFacets = 10;
439
double fFactorVolumen = 40.0;
440
double fFactorArea = 10.0;
444
double fVolumen = fLenghtX * fLenghtY * fLenghtZ;
446
double fVolumenGrid = (fVolumen * ulGridsFacets) / (fFactorVolumen * _ulCtElements);
448
if ((fVolumenGrid * iMaxGrids) < fVolumen) {
449
fVolumenGrid = fVolumen / (float)iMaxGrids;
452
double fLengthGrid = float(pow((float)fVolumenGrid, 1.0F / 3.0F));
454
_ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
455
_ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
456
_ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
460
_ulCtGridsX = 1; // bLenghtXisZero
462
double fArea = fLenghtY * fLenghtZ;
464
double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
466
if ((fAreaGrid * iMaxGrids) < fArea) {
467
fAreaGrid = fArea / (double)iMaxGrids;
470
double fLengthGrid = double(sqrt(fAreaGrid));
472
_ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
473
_ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
476
_ulCtGridsY = 1; // bLenghtYisZero
478
double fArea = fLenghtX * fLenghtZ;
480
double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
482
if ((fAreaGrid * iMaxGrids) < fArea) {
483
fAreaGrid = fArea / (double)iMaxGrids;
486
double fLengthGrid = double(sqrt(fAreaGrid));
488
_ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
489
_ulCtGridsZ = std::max<unsigned long>((unsigned long)(fLenghtZ / fLengthGrid), 1);
492
_ulCtGridsX = 1; // bLenghtXisZero
493
_ulCtGridsY = 1; // bLenghtYisZero
494
_ulCtGridsZ = iMaxGrids; // bLenghtYisZero
497
_ulCtGridsZ = 1; // bLenghtZisZero
499
double fArea = fLenghtX * fLenghtY;
501
double fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
503
if ((fAreaGrid * iMaxGrids) < fArea) {
504
fAreaGrid = fArea / (float)iMaxGrids;
507
double fLengthGrid = double(sqrt(fAreaGrid));
509
_ulCtGridsX = std::max<unsigned long>((unsigned long)(fLenghtX / fLengthGrid), 1);
510
_ulCtGridsY = std::max<unsigned long>((unsigned long)(fLenghtY / fLengthGrid), 1);
513
_ulCtGridsX = 1; // bLenghtXisZero
514
_ulCtGridsZ = 1; // bLenghtZisZero
515
_ulCtGridsY = iMaxGrids; // bLenghtYisZero
518
_ulCtGridsY = 1; // bLenghtYisZero
519
_ulCtGridsZ = 1; // bLenghtZisZero
520
_ulCtGridsX = iMaxGrids; // bLenghtYisZero
523
_ulCtGridsX = iMaxGrids; // bLenghtXisZero
524
_ulCtGridsY = iMaxGrids; // bLenghtYisZero
525
_ulCtGridsZ = iMaxGrids; // bLenghtZisZero
530
void PointsGrid::SearchNearestFromPoint(const Base::Vector3d& rclPt,
531
std::set<unsigned long>& raclInd) const
534
Base::BoundBox3d clBB = GetBoundBox();
536
if (clBB.IsInBox(rclPt)) { // Point lies within
537
unsigned long ulX {};
538
unsigned long ulY {};
539
unsigned long ulZ {};
540
Position(rclPt, ulX, ulY, ulZ);
541
unsigned long ulLevel = 0;
542
while (raclInd.empty()) {
543
GetHull(ulX, ulY, ulZ, ulLevel++, raclInd);
545
GetHull(ulX, ulY, ulZ, ulLevel, raclInd);
547
else { // Point outside
548
Base::BoundBox3d::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.GetCenter() - rclPt);
550
case Base::BoundBox3d::RIGHT: {
552
while (raclInd.empty()) {
553
for (unsigned long i = 0; i < _ulCtGridsY; i++) {
554
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
555
raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
562
case Base::BoundBox3d::LEFT: {
563
int nX = _ulCtGridsX - 1;
564
while (raclInd.empty()) {
565
for (unsigned long i = 0; i < _ulCtGridsY; i++) {
566
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
567
raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
574
case Base::BoundBox3d::TOP: {
576
while (raclInd.empty()) {
577
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
578
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
579
raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
586
case Base::BoundBox3d::BOTTOM: {
587
int nY = _ulCtGridsY - 1;
588
while (raclInd.empty()) {
589
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
590
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
591
raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
598
case Base::BoundBox3d::BACK: {
600
while (raclInd.empty()) {
601
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
602
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
603
raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
610
case Base::BoundBox3d::FRONT: {
611
int nZ = _ulCtGridsZ - 1;
612
while (raclInd.empty()) {
613
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
614
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
615
raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
629
void PointsGrid::GetHull(unsigned long ulX,
632
unsigned long ulDistance,
633
std::set<unsigned long>& raclInd) const
635
int nX1 = std::max<int>(0, int(ulX) - int(ulDistance));
636
int nY1 = std::max<int>(0, int(ulY) - int(ulDistance));
637
int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance));
638
int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance));
639
int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance));
640
int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance));
643
for (int i = nX1; i <= nX2; i++) {
644
for (int j = nY1; j <= nY2; j++) {
645
GetElements(i, j, nZ1, raclInd);
649
for (int i = nX1; i <= nX2; i++) {
650
for (int j = nY1; j <= nY2; j++) {
651
GetElements(i, j, nZ2, raclInd);
655
for (int i = nY1; i <= nY2; i++) {
656
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
657
GetElements(nX1, i, j, raclInd);
661
for (int i = nY1; i <= nY2; i++) {
662
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
663
GetElements(nX2, i, j, raclInd);
667
for (int i = (nX1 + 1); i <= (nX2 - 1); i++) {
668
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
669
GetElements(i, nY1, j, raclInd);
673
for (int i = (nX1 + 1); i <= (nX2 - 1); i++) {
674
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
675
GetElements(i, nY2, j, raclInd);
680
unsigned long PointsGrid::GetElements(unsigned long ulX,
683
std::set<unsigned long>& raclInd) const
685
const std::set<unsigned long>& rclSet = _aulGrid[ulX][ulY][ulZ];
686
if (!rclSet.empty()) {
687
raclInd.insert(rclSet.begin(), rclSet.end());
688
return rclSet.size();
694
void PointsGrid::AddPoint(const Base::Vector3d& rclPt, unsigned long ulPtIndex, float /*fEpsilon*/)
696
unsigned long ulX {}, ulY {}, ulZ {};
697
Pos(Base::Vector3d(rclPt.x, rclPt.y, rclPt.z), ulX, ulY, ulZ);
698
if ((ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ)) {
699
_aulGrid[ulX][ulY][ulZ].insert(ulPtIndex);
703
void PointsGrid::Validate(const PointKernel& rclPoints)
705
if (_pclPoints != &rclPoints) {
708
else if (rclPoints.size() != _ulCtElements) {
713
void PointsGrid::Validate()
719
if (_pclPoints->size() != _ulCtElements) {
724
bool PointsGrid::Verify() const
727
return false; // no point cloud attached
729
if (_pclPoints->size() != _ulCtElements) {
730
return false; // not up-to-date
733
PointsGridIterator it(*this);
734
for (it.Init(); it.More(); it.Next()) {
735
std::vector<unsigned long> aulElements;
736
it.GetElements(aulElements);
737
for (unsigned long element : aulElements) {
738
const Base::Vector3d& cP = _pclPoints->getPoint(element);
739
if (!it.GetBoundBox().IsInBox(cP)) {
740
return false; // point doesn't lie inside the grid element
748
void PointsGrid::RebuildGrid()
750
_ulCtElements = _pclPoints->size();
754
// Fill data structure
757
for (const auto& pnt : *_pclPoints) {
762
void PointsGrid::Pos(const Base::Vector3d& rclPoint,
765
unsigned long& rulZ) const
767
rulX = (unsigned long)((rclPoint.x - _fMinX) / _fGridLenX);
768
rulY = (unsigned long)((rclPoint.y - _fMinY) / _fGridLenY);
769
rulZ = (unsigned long)((rclPoint.z - _fMinZ) / _fGridLenZ);
772
unsigned long PointsGrid::FindElements(const Base::Vector3d& rclPoint,
773
std::set<unsigned long>& aulElements) const
775
unsigned long ulX {}, ulY {}, ulZ {};
776
Pos(rclPoint, ulX, ulY, ulZ);
778
// check if the given point is inside the grid structure
779
if ((ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ)) {
780
return GetElements(ulX, ulY, ulZ, aulElements);
786
// ----------------------------------------------------------------
788
PointsGridIterator::PointsGridIterator(const PointsGrid& rclG)
790
, _clPt(0.0F, 0.0F, 0.0F)
791
, _clDir(0.0F, 0.0F, 0.0F)
794
bool PointsGridIterator::InitOnRay(const Base::Vector3d& rclPt,
795
const Base::Vector3d& rclDir,
796
float fMaxSearchArea,
797
std::vector<unsigned long>& raulElements)
799
bool ret = InitOnRay(rclPt, rclDir, raulElements);
800
_fMaxSearchArea = fMaxSearchArea;
804
bool PointsGridIterator::InitOnRay(const Base::Vector3d& rclPt,
805
const Base::Vector3d& rclDir,
806
std::vector<unsigned long>& raulElements)
808
// needed in NextOnRay() to avoid an infinite loop
809
_cSearchPositions.clear();
811
_fMaxSearchArea = FLOAT_MAX;
813
raulElements.clear();
819
// point lies within global BB
820
if (_rclGrid.GetBoundBox().IsInBox(rclPt)) { // determine the voxel by the starting point
821
_rclGrid.Position(rclPt, _ulX, _ulY, _ulZ);
822
raulElements.insert(raulElements.end(),
823
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(),
824
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
827
else { // StartPoint outside
828
Base::Vector3d cP0, cP1;
829
if (_rclGrid.GetBoundBox().IntersectWithLine(rclPt,
832
cP1)) { // determine the next point
833
if ((cP0 - rclPt).Length() < (cP1 - rclPt).Length()) {
834
_rclGrid.Position(cP0, _ulX, _ulY, _ulZ);
837
_rclGrid.Position(cP1, _ulX, _ulY, _ulZ);
840
raulElements.insert(raulElements.end(),
841
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(),
842
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
850
bool PointsGridIterator::NextOnRay(std::vector<unsigned long>& raulElements)
853
return false; // not initialized or beam exited
856
raulElements.clear();
858
Base::Vector3d clIntersectPoint;
860
// Look for the next adjacent BB on the search beam
861
Base::BoundBox3d::SIDE tSide =
862
_rclGrid.GetBoundBox(_ulX, _ulY, _ulZ).GetSideFromRay(_clPt, _clDir, clIntersectPoint);
866
if ((_clPt - clIntersectPoint).Length() > _fMaxSearchArea) {
871
case Base::BoundBox3d::LEFT:
874
case Base::BoundBox3d::RIGHT:
877
case Base::BoundBox3d::BOTTOM:
880
case Base::BoundBox3d::TOP:
883
case Base::BoundBox3d::FRONT:
886
case Base::BoundBox3d::BACK:
891
case Base::BoundBox3d::INVALID:
896
GridElement pos(_ulX, _ulY, _ulZ);
897
if (_cSearchPositions.find(pos) != _cSearchPositions.end()) {
899
false; // grid element already visited => result from GetSideFromRay invalid
903
if (_bValidRay && _rclGrid.CheckPos(_ulX, _ulY, _ulZ)) {
904
GridElement pos(_ulX, _ulY, _ulZ);
905
_cSearchPositions.insert(pos);
906
raulElements.insert(raulElements.end(),
907
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(),
908
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
911
_bValidRay = false; // ray exited