1
/***************************************************************************
2
* Copyright (c) 2005 Imetric 3D GmbH *
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"
32
#include "MeshKernel.h"
35
using namespace MeshCore;
37
MeshGrid::MeshGrid(const MeshKernel& rclM)
54
, _ulCtGridsX(MESH_CT_GRID)
55
, _ulCtGridsY(MESH_CT_GRID)
56
, _ulCtGridsZ(MESH_CT_GRID)
65
void MeshGrid::Attach(const MeshKernel& rclM)
77
void MeshGrid::Rebuild(unsigned long ulX, unsigned long ulY, unsigned long ulZ)
82
_ulCtElements = HasElements();
86
void MeshGrid::Rebuild(unsigned long ulPerGrid, unsigned long ulMaxGrid)
88
_ulCtElements = HasElements();
89
CalculateGridLength(ulPerGrid, ulMaxGrid);
93
void MeshGrid::Rebuild(int iCtGridPerAxis)
95
_ulCtElements = HasElements();
96
CalculateGridLength(iCtGridPerAxis);
100
void MeshGrid::InitGrid()
104
// Calculate grid length if not initialised
106
if ((_ulCtGridsX == 0) || (_ulCtGridsY == 0) || (_ulCtGridsZ == 0)) {
107
CalculateGridLength(MESH_CT_GRID, MESH_MAX_GRIDS);
110
// Determine grid length and offset
113
Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
115
float fLengthX = clBBMesh.LengthX();
116
float fLengthY = clBBMesh.LengthY();
117
float fLengthZ = clBBMesh.LengthZ();
122
_fGridLenX = (1.0f + fLengthX) / float(_ulCtGridsX);
123
_fMinX = clBBMesh.MinX - 0.5f;
127
_fGridLenY = (1.0f + fLengthY) / float(_ulCtGridsY);
128
_fMinY = clBBMesh.MinY - 0.5f;
132
_fGridLenZ = (1.0f + fLengthZ) / float(_ulCtGridsZ);
133
_fMinZ = clBBMesh.MinZ - 0.5f;
137
// Create data structure
139
_aulGrid.resize(_ulCtGridsX);
140
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
141
_aulGrid[i].resize(_ulCtGridsY);
142
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
143
_aulGrid[i][j].resize(_ulCtGridsZ);
148
unsigned long MeshGrid::Inside(const Base::BoundBox3f& rclBB,
149
std::vector<ElementIndex>& raulElements,
150
bool bDelDoubles) const
152
unsigned long ulMinX {}, ulMinY {}, ulMinZ {}, ulMaxX {}, ulMaxY {}, ulMaxZ {};
154
raulElements.clear();
156
// Grid boxes for a more detailed selection
157
Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
158
Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
160
for (auto i = ulMinX; i <= ulMaxX; i++) {
161
for (auto j = ulMinY; j <= ulMaxY; j++) {
162
for (auto k = ulMinZ; k <= ulMaxZ; k++) {
163
raulElements.insert(raulElements.end(),
164
_aulGrid[i][j][k].begin(),
165
_aulGrid[i][j][k].end());
171
// remove duplicate mentions
172
std::sort(raulElements.begin(), raulElements.end());
173
raulElements.erase(std::unique(raulElements.begin(), raulElements.end()),
177
return raulElements.size();
180
unsigned long MeshGrid::Inside(const Base::BoundBox3f& rclBB,
181
std::vector<ElementIndex>& raulElements,
182
const Base::Vector3f& rclOrg,
184
bool bDelDoubles) const
186
unsigned long ulMinX {}, ulMinY {}, ulMinZ {}, ulMaxX {}, ulMaxY {}, ulMaxZ {};
187
float fGridDiag = GetBoundBox(0, 0, 0).CalcDiagonalLength();
188
float fMinDistP2 = (fGridDiag * fGridDiag) + (fMaxDist * fMaxDist);
190
raulElements.clear();
192
// Grid boxes for a more detailed selection
193
Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
194
Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
196
for (auto i = ulMinX; i <= ulMaxX; i++) {
197
for (auto j = ulMinY; j <= ulMaxY; j++) {
198
for (auto k = ulMinZ; k <= ulMaxZ; k++) {
199
if (Base::DistanceP2(GetBoundBox(i, j, k).GetCenter(), rclOrg) < fMinDistP2) {
200
raulElements.insert(raulElements.end(),
201
_aulGrid[i][j][k].begin(),
202
_aulGrid[i][j][k].end());
209
// remove duplicate mentions
210
std::sort(raulElements.begin(), raulElements.end());
211
raulElements.erase(std::unique(raulElements.begin(), raulElements.end()),
215
return raulElements.size();
218
unsigned long MeshGrid::Inside(const Base::BoundBox3f& rclBB,
219
std::set<ElementIndex>& raulElements) const
221
unsigned long ulMinX {}, ulMinY {}, ulMinZ {}, ulMaxX {}, ulMaxY {}, ulMaxZ {};
223
raulElements.clear();
225
// Grid boxes for a more detailed selection
226
Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ);
227
Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ);
229
for (auto i = ulMinX; i <= ulMaxX; i++) {
230
for (auto j = ulMinY; j <= ulMaxY; j++) {
231
for (auto k = ulMinZ; k <= ulMaxZ; k++) {
232
raulElements.insert(_aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end());
237
return raulElements.size();
240
bool MeshGrid::CheckPosition(const Base::Vector3f& rclPoint,
243
unsigned long& rulZ) const
245
rulX = static_cast<unsigned long>((rclPoint.x - _fMinX) / _fGridLenX);
246
rulY = static_cast<unsigned long>((rclPoint.y - _fMinY) / _fGridLenY);
247
rulZ = static_cast<unsigned long>((rclPoint.z - _fMinZ) / _fGridLenZ);
249
if ((rulX < _ulCtGridsX) && (rulY < _ulCtGridsY) && (rulZ < _ulCtGridsZ)) {
256
void MeshGrid::Position(const Base::Vector3f& rclPoint,
259
unsigned long& rulZ) const
261
if (rclPoint.x <= _fMinX) {
266
std::min<unsigned long>(static_cast<unsigned long>((rclPoint.x - _fMinX) / _fGridLenX),
270
if (rclPoint.y <= _fMinY) {
275
std::min<unsigned long>(static_cast<unsigned long>((rclPoint.y - _fMinY) / _fGridLenY),
279
if (rclPoint.z <= _fMinZ) {
284
std::min<unsigned long>(static_cast<unsigned long>((rclPoint.z - _fMinZ) / _fGridLenZ),
289
void MeshGrid::CalculateGridLength(unsigned long ulCtGrid, unsigned long ulMaxGrids)
291
// Calculate grid lengths or number of grids per dimension
292
// There should be about 10 (?!?!) facets per grid
293
// respectively max grids should not exceed 10000
294
Base::BoundBox3f clBBMeshEnlarged = _pclMesh->GetBoundBox();
297
float fLenX = clBBMeshEnlarged.LengthX();
298
float fLenY = clBBMeshEnlarged.LengthY();
299
float fLenZ = clBBMeshEnlarged.LengthZ();
301
float fVolume = fLenX * fLenY * fLenZ;
302
if (fVolume > 0.0f) {
304
if (_ulCtElements > (ulMaxGrids * ulCtGrid)) {
305
fVolElem = (fLenX * fLenY * fLenZ) / float(ulMaxGrids * ulCtGrid);
308
fVolElem = (fLenX * fLenY * fLenZ) / float(_ulCtElements);
311
float fVol = fVolElem * float(ulCtGrid);
312
fGridLen = float(pow(fVol, 1.0f / 3.0f));
315
// Planar bounding box
316
float fArea = fLenX * fLenY + fLenX * fLenZ + fLenY * fLenZ;
318
if (_ulCtElements > (ulMaxGrids * ulCtGrid)) {
319
fAreaElem = fArea / float(ulMaxGrids * ulCtGrid);
322
fAreaElem = fArea / float(_ulCtElements);
325
float fRepresentativeArea = fAreaElem * static_cast<float>(ulCtGrid);
326
fGridLen = sqrt(fRepresentativeArea);
330
_ulCtGridsX = std::max<unsigned long>(static_cast<unsigned long>(fLenX / fGridLen), 1);
331
_ulCtGridsY = std::max<unsigned long>(static_cast<unsigned long>(fLenY / fGridLen), 1);
332
_ulCtGridsZ = std::max<unsigned long>(static_cast<unsigned long>(fLenZ / fGridLen), 1);
342
void MeshGrid::CalculateGridLength(int iCtGridPerAxis)
344
if (iCtGridPerAxis <= 0) {
345
CalculateGridLength(MESH_CT_GRID, MESH_MAX_GRIDS);
349
// Calculate grid lengths or number of grids per dimension
350
// There should be about 10 (?!?!) facets per grid
351
// respectively max grids should not exceed 10000
352
Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
354
float fLenghtX = clBBMesh.LengthX();
355
float fLenghtY = clBBMesh.LengthY();
356
float fLenghtZ = clBBMesh.LengthZ();
358
float fLenghtD = clBBMesh.CalcDiagonalLength();
360
float fLengthTol = 0.05f * fLenghtD;
362
bool bLenghtXisZero = (fLenghtX <= fLengthTol);
363
bool bLenghtYisZero = (fLenghtY <= fLengthTol);
364
bool bLenghtZisZero = (fLenghtZ <= fLengthTol);
370
if (bLenghtXisZero) {
374
iMaxGrids *= iCtGridPerAxis;
377
if (bLenghtYisZero) {
381
iMaxGrids *= iCtGridPerAxis;
384
if (bLenghtZisZero) {
388
iMaxGrids *= iCtGridPerAxis;
391
unsigned long ulGridsFacets = 10;
393
float fFactorVolumen = 40.0;
394
float fFactorArea = 10.0;
398
float fVolumen = fLenghtX * fLenghtY * fLenghtZ;
400
float fVolumenGrid = (fVolumen * ulGridsFacets) / (fFactorVolumen * _ulCtElements);
402
if ((fVolumenGrid * iMaxGrids) < fVolumen) {
403
fVolumenGrid = fVolumen / static_cast<float>(iMaxGrids);
406
float fLengthGrid = pow(fVolumenGrid, 1.0f / 3.0f);
409
std::max<unsigned long>(static_cast<unsigned long>(fLenghtX / fLengthGrid), 1);
411
std::max<unsigned long>(static_cast<unsigned long>(fLenghtY / fLengthGrid), 1);
413
std::max<unsigned long>(static_cast<unsigned long>(fLenghtZ / fLengthGrid), 1);
417
_ulCtGridsX = 1; // bLenghtXisZero
419
float fArea = fLenghtY * fLenghtZ;
421
float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
423
if ((fAreaGrid * iMaxGrids) < fArea) {
424
fAreaGrid = fArea / static_cast<float>(iMaxGrids);
427
float fLengthGrid = float(sqrt(fAreaGrid));
430
std::max<unsigned long>(static_cast<unsigned long>(fLenghtY / fLengthGrid), 1);
432
std::max<unsigned long>(static_cast<unsigned long>(fLenghtZ / fLengthGrid), 1);
435
_ulCtGridsY = 1; // bLenghtYisZero
437
float fArea = fLenghtX * fLenghtZ;
439
float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
441
if ((fAreaGrid * iMaxGrids) < fArea) {
442
fAreaGrid = fArea / static_cast<float>(iMaxGrids);
445
float fLengthGrid = float(sqrt(fAreaGrid));
448
std::max<unsigned long>(static_cast<unsigned long>(fLenghtX / fLengthGrid), 1);
450
std::max<unsigned long>(static_cast<unsigned long>(fLenghtZ / fLengthGrid), 1);
453
_ulCtGridsX = 1; // bLenghtXisZero
454
_ulCtGridsY = 1; // bLenghtYisZero
455
_ulCtGridsZ = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero
458
_ulCtGridsZ = 1; // bLenghtZisZero
460
float fArea = fLenghtX * fLenghtY;
462
float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements);
464
if ((fAreaGrid * iMaxGrids) < fArea) {
465
fAreaGrid = fArea / static_cast<float>(iMaxGrids);
468
float fLengthGrid = float(sqrt(fAreaGrid));
471
std::max<unsigned long>(static_cast<unsigned long>(fLenghtX / fLengthGrid), 1);
473
std::max<unsigned long>(static_cast<unsigned long>(fLenghtY / fLengthGrid), 1);
476
_ulCtGridsX = 1; // bLenghtXisZero
477
_ulCtGridsZ = 1; // bLenghtZisZero
478
_ulCtGridsY = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero
481
_ulCtGridsY = 1; // bLenghtYisZero
482
_ulCtGridsZ = 1; // bLenghtZisZero
483
_ulCtGridsX = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero
486
_ulCtGridsX = static_cast<unsigned long>(iMaxGrids); // bLenghtXisZero
487
_ulCtGridsY = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero
488
_ulCtGridsZ = static_cast<unsigned long>(iMaxGrids); // bLenghtZisZero
493
void MeshGrid::SearchNearestFromPoint(const Base::Vector3f& rclPt,
494
std::set<ElementIndex>& raclInd) const
497
Base::BoundBox3f clBB = GetBoundBox();
499
if (clBB.IsInBox(rclPt)) { // Point lies within
500
unsigned long ulX {}, ulY {}, ulZ {};
501
Position(rclPt, ulX, ulY, ulZ);
502
// int nX = ulX, nY = ulY, nZ = ulZ;
503
unsigned long ulMaxLevel =
504
std::max<unsigned long>(_ulCtGridsX, std::max<unsigned long>(_ulCtGridsY, _ulCtGridsZ));
505
unsigned long ulLevel = 0;
506
while (raclInd.empty() && ulLevel <= ulMaxLevel) {
507
GetHull(ulX, ulY, ulZ, ulLevel++, raclInd);
509
GetHull(ulX, ulY, ulZ, ulLevel, raclInd);
511
else { // Point outside
512
Base::BoundBox3f::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.GetCenter() - rclPt);
514
case Base::BoundBox3f::RIGHT: {
515
unsigned long nX = 0;
516
while (raclInd.empty() && nX < _ulCtGridsX) {
517
for (unsigned long i = 0; i < _ulCtGridsY; i++) {
518
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
519
raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
526
case Base::BoundBox3f::LEFT: {
527
unsigned long nX = _ulCtGridsX - 1;
528
while (raclInd.empty() && nX < _ulCtGridsX) {
529
for (unsigned long i = 0; i < _ulCtGridsY; i++) {
530
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
531
raclInd.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end());
538
case Base::BoundBox3f::TOP: {
539
unsigned long nY = 0;
540
while (raclInd.empty() && nY < _ulCtGridsY) {
541
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
542
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
543
raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
550
case Base::BoundBox3f::BOTTOM: {
551
unsigned long nY = _ulCtGridsY - 1;
552
while (raclInd.empty() && nY < _ulCtGridsY) {
553
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
554
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
555
raclInd.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end());
562
case Base::BoundBox3f::BACK: {
563
unsigned long nZ = 0;
564
while (raclInd.empty() && nZ < _ulCtGridsZ) {
565
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
566
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
567
raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
574
case Base::BoundBox3f::FRONT: {
575
unsigned long nZ = _ulCtGridsZ - 1;
576
while (raclInd.empty() && nZ < _ulCtGridsZ) {
577
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
578
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
579
raclInd.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end());
593
void MeshGrid::GetHull(unsigned long ulX,
596
unsigned long ulDistance,
597
std::set<ElementIndex>& raclInd) const
599
int nX1 = std::max<int>(0, int(ulX) - int(ulDistance));
600
int nY1 = std::max<int>(0, int(ulY) - int(ulDistance));
601
int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance));
602
int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance));
603
int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance));
604
int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance));
607
for (int i = nX1; i <= nX2; i++) {
608
for (int j = nY1; j <= nY2; j++) {
609
GetElements(static_cast<unsigned long>(i),
610
static_cast<unsigned long>(j),
611
static_cast<unsigned long>(nZ1),
616
for (int i = nX1; i <= nX2; i++) {
617
for (int j = nY1; j <= nY2; j++) {
618
GetElements(static_cast<unsigned long>(i),
619
static_cast<unsigned long>(j),
620
static_cast<unsigned long>(nZ2),
625
for (int i = nY1; i <= nY2; i++) {
626
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
627
GetElements(static_cast<unsigned long>(nX1),
628
static_cast<unsigned long>(i),
629
static_cast<unsigned long>(j),
634
for (int i = nY1; i <= nY2; i++) {
635
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
636
GetElements(static_cast<unsigned long>(nX2),
637
static_cast<unsigned long>(i),
638
static_cast<unsigned long>(j),
643
for (int i = (nX1 + 1); i <= (nX2 - 1); i++) {
644
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
645
GetElements(static_cast<unsigned long>(i),
646
static_cast<unsigned long>(nY1),
647
static_cast<unsigned long>(j),
652
for (int i = (nX1 + 1); i <= (nX2 - 1); i++) {
653
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
654
GetElements(static_cast<unsigned long>(i),
655
static_cast<unsigned long>(nY2),
656
static_cast<unsigned long>(j),
662
unsigned long MeshGrid::GetElements(unsigned long ulX,
665
std::set<ElementIndex>& raclInd) const
667
const std::set<ElementIndex>& rclSet = _aulGrid[ulX][ulY][ulZ];
668
if (!rclSet.empty()) {
669
raclInd.insert(rclSet.begin(), rclSet.end());
670
return rclSet.size();
676
unsigned long MeshGrid::GetElements(const Base::Vector3f& rclPoint,
677
std::vector<ElementIndex>& aulFacets) const
679
unsigned long ulX {}, ulY {}, ulZ {};
680
if (!CheckPosition(rclPoint, ulX, ulY, ulZ)) {
684
aulFacets.resize(_aulGrid[ulX][ulY][ulZ].size());
686
std::copy(_aulGrid[ulX][ulY][ulZ].begin(), _aulGrid[ulX][ulY][ulZ].end(), aulFacets.begin());
687
return aulFacets.size();
691
MeshGrid::GetIndexToPosition(unsigned long ulX, unsigned long ulY, unsigned long ulZ) const
693
if (!CheckPos(ulX, ulY, ulZ)) {
696
return (ulZ * _ulCtGridsY + ulY) * _ulCtGridsX + ulX;
699
bool MeshGrid::GetPositionToIndex(unsigned long id,
702
unsigned long& ulZ) const
704
ulX = id % _ulCtGridsX;
705
ulY = (id / _ulCtGridsX) % _ulCtGridsY;
706
ulZ = id / (_ulCtGridsX * _ulCtGridsY);
708
if (!CheckPos(ulX, ulY, ulZ)) {
718
// ----------------------------------------------------------------
720
MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM)
723
MeshFacetGrid::RebuildGrid();
726
MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM, int iCtGridPerAxis)
729
Rebuild(iCtGridPerAxis);
732
MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM,
738
Rebuild(ulX, ulY, ulZ);
741
MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM, float fGridLen)
744
Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
745
Rebuild(std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthX() / fGridLen), 1),
746
std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthY() / fGridLen), 1),
747
std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthZ() / fGridLen), 1));
750
void MeshFacetGrid::Validate(const MeshKernel& rclMesh)
752
if (_pclMesh != &rclMesh) {
755
else if (rclMesh.CountFacets() != _ulCtElements) {
760
void MeshFacetGrid::Validate()
766
if (_pclMesh->CountFacets() != _ulCtElements) {
771
bool MeshFacetGrid::Verify() const
774
return false; // no mesh attached
776
if (_pclMesh->CountFacets() != _ulCtElements) {
777
return false; // not up-to-date
780
MeshGridIterator it(*this);
781
MeshFacetIterator cF(*_pclMesh);
782
for (it.Init(); it.More(); it.Next()) {
783
std::vector<ElementIndex> aulElements;
784
it.GetElements(aulElements);
785
for (ElementIndex element : aulElements) {
787
if (!cF->IntersectBoundingBox(it.GetBoundBox())) {
788
return false; // no intersection between facet although the facet is in grid
796
void MeshFacetGrid::RebuildGrid()
798
_ulCtElements = _pclMesh->CountFacets();
802
// Fill data structure
803
MeshFacetIterator clFIter(*_pclMesh);
806
for (clFIter.Init(); clFIter.More(); clFIter.Next()) {
807
// AddFacet(*clFIter, i++, 2.0f);
808
AddFacet(*clFIter, i++);
812
unsigned long MeshFacetGrid::SearchNearestFromPoint(const Base::Vector3f& rclPt) const
814
ElementIndex ulFacetInd = ELEMENT_INDEX_MAX;
815
float fMinDist = FLOAT_MAX;
816
Base::BoundBox3f clBB = GetBoundBox();
818
if (clBB.IsInBox(rclPt)) { // Point lies within
819
unsigned long ulX {}, ulY {}, ulZ {};
820
Position(rclPt, ulX, ulY, ulZ);
821
float fMinGridDist = std::min<float>(std::min<float>(_fGridLenX, _fGridLenY), _fGridLenZ);
822
unsigned long ulDistance = 0;
823
while (fMinDist > (fMinGridDist * float(ulDistance))) {
824
SearchNearestFacetInHull(ulX, ulY, ulZ, ulDistance, rclPt, ulFacetInd, fMinDist);
827
SearchNearestFacetInHull(ulX, ulY, ulZ, ulDistance, rclPt, ulFacetInd, fMinDist);
829
else { // Point outside
830
Base::BoundBox3f::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.GetCenter() - rclPt);
832
case Base::BoundBox3f::RIGHT: {
833
unsigned long nX = 0;
834
while ((fMinDist > ((clBB.MinX - rclPt.x) + (float(nX) * _fGridLenX)))
835
&& (nX < _ulCtGridsX)) {
836
for (unsigned long i = 0; i < _ulCtGridsY; i++) {
837
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
838
SearchNearestFacetInGrid(nX, i, j, rclPt, fMinDist, ulFacetInd);
845
case Base::BoundBox3f::LEFT: {
846
unsigned long nX = _ulCtGridsX - 1;
847
while ((fMinDist > ((rclPt.x - clBB.MinX) + (float(nX) * _fGridLenX)))
848
&& (nX < _ulCtGridsX)) {
849
for (unsigned long i = 0; i < _ulCtGridsY; i++) {
850
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
851
SearchNearestFacetInGrid(nX, i, j, rclPt, fMinDist, ulFacetInd);
858
case Base::BoundBox3f::TOP: {
859
unsigned long nY = 0;
860
while ((fMinDist > ((clBB.MinY - rclPt.y) + (float(nY) * _fGridLenY)))
861
&& (nY < _ulCtGridsY)) {
862
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
863
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
864
SearchNearestFacetInGrid(i, nY, j, rclPt, fMinDist, ulFacetInd);
871
case Base::BoundBox3f::BOTTOM: {
872
unsigned long nY = _ulCtGridsY - 1;
873
while ((fMinDist > ((rclPt.y - clBB.MinY) + (float(nY) * _fGridLenY)))
874
&& (nY < _ulCtGridsY)) {
875
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
876
for (unsigned long j = 0; j < _ulCtGridsZ; j++) {
877
SearchNearestFacetInGrid(i, nY, j, rclPt, fMinDist, ulFacetInd);
884
case Base::BoundBox3f::BACK: {
885
unsigned long nZ = 0;
886
while ((fMinDist > ((clBB.MinZ - rclPt.z) + (float(nZ) * _fGridLenZ)))
887
&& (nZ < _ulCtGridsZ)) {
888
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
889
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
890
SearchNearestFacetInGrid(i, j, nZ, rclPt, fMinDist, ulFacetInd);
897
case Base::BoundBox3f::FRONT: {
898
unsigned long nZ = _ulCtGridsZ - 1;
899
while ((fMinDist > ((rclPt.z - clBB.MinZ) + (float(nZ) * _fGridLenZ)))
900
&& (nZ < _ulCtGridsZ)) {
901
for (unsigned long i = 0; i < _ulCtGridsX; i++) {
902
for (unsigned long j = 0; j < _ulCtGridsY; j++) {
903
SearchNearestFacetInGrid(i, j, nZ, rclPt, fMinDist, ulFacetInd);
918
unsigned long MeshFacetGrid::SearchNearestFromPoint(const Base::Vector3f& rclPt,
919
float fMaxSearchArea) const
921
std::vector<ElementIndex> aulFacets;
922
ElementIndex ulFacetInd = ELEMENT_INDEX_MAX;
923
float fMinDist = fMaxSearchArea;
925
MeshAlgorithm clFTool(*_pclMesh);
927
Base::BoundBox3f clBB(rclPt.x - fMaxSearchArea,
928
rclPt.y - fMaxSearchArea,
929
rclPt.z - fMaxSearchArea,
930
rclPt.x + fMaxSearchArea,
931
rclPt.y + fMaxSearchArea,
932
rclPt.z + fMaxSearchArea);
934
Inside(clBB, aulFacets, rclPt, fMaxSearchArea, true);
936
for (ElementIndex facet : aulFacets) {
939
if (clFTool.Distance(rclPt, facet, fMinDist, fDist)) {
948
void MeshFacetGrid::SearchNearestFacetInHull(unsigned long ulX,
951
unsigned long ulDistance,
952
const Base::Vector3f& rclPt,
953
ElementIndex& rulFacetInd,
954
float& rfMinDist) const
956
int nX1 = std::max<int>(0, int(ulX) - int(ulDistance));
957
int nY1 = std::max<int>(0, int(ulY) - int(ulDistance));
958
int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance));
959
int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance));
960
int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance));
961
int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance));
964
for (int i = nX1; i <= nX2; i++) {
965
for (int j = nY1; j <= nY2; j++) {
966
SearchNearestFacetInGrid(static_cast<unsigned long>(i),
967
static_cast<unsigned long>(j),
968
static_cast<unsigned long>(nZ1),
975
for (int i = nX1; i <= nX2; i++) {
976
for (int j = nY1; j <= nY2; j++) {
977
SearchNearestFacetInGrid(static_cast<unsigned long>(i),
978
static_cast<unsigned long>(j),
979
static_cast<unsigned long>(nZ2),
986
for (int i = nY1; i <= nY2; i++) {
987
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
988
SearchNearestFacetInGrid(static_cast<unsigned long>(nX1),
989
static_cast<unsigned long>(i),
990
static_cast<unsigned long>(j),
997
for (int i = nY1; i <= nY2; i++) {
998
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
999
SearchNearestFacetInGrid(static_cast<unsigned long>(nX2),
1000
static_cast<unsigned long>(i),
1001
static_cast<unsigned long>(j),
1008
for (int i = (nX1 + 1); i <= (nX2 - 1); i++) {
1009
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
1010
SearchNearestFacetInGrid(static_cast<unsigned long>(i),
1011
static_cast<unsigned long>(nY1),
1012
static_cast<unsigned long>(j),
1019
for (int i = (nX1 + 1); i <= (nX2 - 1); i++) {
1020
for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) {
1021
SearchNearestFacetInGrid(static_cast<unsigned long>(i),
1022
static_cast<unsigned long>(nY2),
1023
static_cast<unsigned long>(j),
1031
void MeshFacetGrid::SearchNearestFacetInGrid(unsigned long ulX,
1034
const Base::Vector3f& rclPt,
1036
ElementIndex& rulFacetInd) const
1038
const std::set<ElementIndex>& rclSet = _aulGrid[ulX][ulY][ulZ];
1039
for (ElementIndex pI : rclSet) {
1040
float fDist = _pclMesh->GetFacet(pI).DistanceToPoint(rclPt);
1041
if (fDist < rfMinDist) {
1048
//----------------------------------------------------------------------------
1050
MeshPointGrid::MeshPointGrid(const MeshKernel& rclM)
1053
MeshPointGrid::RebuildGrid();
1056
MeshPointGrid::MeshPointGrid()
1060
MeshPointGrid::MeshPointGrid(const MeshKernel& rclM,
1066
Rebuild(ulX, ulY, ulZ);
1069
MeshPointGrid::MeshPointGrid(const MeshKernel& rclM, int iCtGridPerAxis)
1072
Rebuild(iCtGridPerAxis);
1075
MeshPointGrid::MeshPointGrid(const MeshKernel& rclM, float fGridLen)
1078
Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox();
1079
Rebuild(std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthX() / fGridLen), 1),
1080
std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthY() / fGridLen), 1),
1081
std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthZ() / fGridLen), 1));
1084
void MeshPointGrid::AddPoint(const MeshPoint& rclPt, ElementIndex ulPtIndex, float fEpsilon)
1087
unsigned long ulX {}, ulY {}, ulZ {};
1088
Pos(Base::Vector3f(rclPt.x, rclPt.y, rclPt.z), ulX, ulY, ulZ);
1089
if ((ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ)) {
1090
_aulGrid[ulX][ulY][ulZ].insert(ulPtIndex);
1094
void MeshPointGrid::Validate(const MeshKernel& rclMesh)
1096
if (_pclMesh != &rclMesh) {
1099
else if (rclMesh.CountPoints() != _ulCtElements) {
1104
void MeshPointGrid::Validate()
1110
if (_pclMesh->CountPoints() != _ulCtElements) {
1115
bool MeshPointGrid::Verify() const
1118
return false; // no mesh attached
1120
if (_pclMesh->CountFacets() != _ulCtElements) {
1121
return false; // not up-to-date
1124
MeshGridIterator it(*this);
1125
MeshPointIterator cP(*_pclMesh);
1126
for (it.Init(); it.More(); it.Next()) {
1127
std::vector<ElementIndex> aulElements;
1128
it.GetElements(aulElements);
1129
for (ElementIndex element : aulElements) {
1131
if (!it.GetBoundBox().IsInBox(*cP)) {
1132
return false; // point doesn't lie inside the grid element
1140
void MeshPointGrid::RebuildGrid()
1142
_ulCtElements = _pclMesh->CountPoints();
1146
// Fill data structure
1148
MeshPointIterator cPIter(*_pclMesh);
1150
unsigned long i = 0;
1151
for (cPIter.Init(); cPIter.More(); cPIter.Next()) {
1152
AddPoint(*cPIter, i++);
1156
void MeshPointGrid::Pos(const Base::Vector3f& rclPoint,
1157
unsigned long& rulX,
1158
unsigned long& rulY,
1159
unsigned long& rulZ) const
1161
rulX = static_cast<unsigned long>((rclPoint.x - _fMinX) / _fGridLenX);
1162
rulY = static_cast<unsigned long>((rclPoint.y - _fMinY) / _fGridLenY);
1163
rulZ = static_cast<unsigned long>((rclPoint.z - _fMinZ) / _fGridLenZ);
1166
unsigned long MeshPointGrid::FindElements(const Base::Vector3f& rclPoint,
1167
std::set<ElementIndex>& aulElements) const
1169
unsigned long ulX {}, ulY {}, ulZ {};
1170
Pos(rclPoint, ulX, ulY, ulZ);
1172
// check if the given point is inside the grid structure
1173
if ((ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ)) {
1174
return GetElements(ulX, ulY, ulZ, aulElements);
1180
// ----------------------------------------------------------------
1182
MeshGridIterator::MeshGridIterator(const MeshGrid& rclG)
1184
, _clPt(0.0f, 0.0f, 0.0f)
1185
, _clDir(0.0f, 0.0f, 0.0f)
1188
bool MeshGridIterator::InitOnRay(const Base::Vector3f& rclPt,
1189
const Base::Vector3f& rclDir,
1190
float fMaxSearchArea,
1191
std::vector<ElementIndex>& raulElements)
1193
bool ret = InitOnRay(rclPt, rclDir, raulElements);
1194
_fMaxSearchArea = fMaxSearchArea;
1198
bool MeshGridIterator::InitOnRay(const Base::Vector3f& rclPt,
1199
const Base::Vector3f& rclDir,
1200
std::vector<ElementIndex>& raulElements)
1202
// needed in NextOnRay() to avoid an infinite loop
1203
_cSearchPositions.clear();
1205
_fMaxSearchArea = FLOAT_MAX;
1207
raulElements.clear();
1213
// point lies within global BB
1214
if (_rclGrid.GetBoundBox().IsInBox(rclPt)) { // Determine the voxel by the starting point
1215
_rclGrid.Position(rclPt, _ulX, _ulY, _ulZ);
1216
raulElements.insert(raulElements.end(),
1217
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(),
1218
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
1221
else { // Start point outside
1222
Base::Vector3f cP0, cP1;
1223
if (_rclGrid.GetBoundBox().IntersectWithLine(rclPt,
1226
cP1)) { // determine the next point
1227
if ((cP0 - rclPt).Length() < (cP1 - rclPt).Length()) {
1228
_rclGrid.Position(cP0, _ulX, _ulY, _ulZ);
1231
_rclGrid.Position(cP1, _ulX, _ulY, _ulZ);
1234
raulElements.insert(raulElements.end(),
1235
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(),
1236
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
1244
bool MeshGridIterator::NextOnRay(std::vector<ElementIndex>& raulElements)
1247
return false; // not initialized or beam exited
1250
raulElements.clear();
1252
Base::Vector3f clIntersectPoint;
1254
// Look for the next adjacent BB on the search beam
1255
Base::BoundBox3f::SIDE tSide =
1256
_rclGrid.GetBoundBox(_ulX, _ulY, _ulZ).GetSideFromRay(_clPt, _clDir, clIntersectPoint);
1260
if ((_clPt - clIntersectPoint).Length() > _fMaxSearchArea) {
1265
case Base::BoundBox3f::LEFT:
1268
case Base::BoundBox3f::RIGHT:
1271
case Base::BoundBox3f::BOTTOM:
1274
case Base::BoundBox3f::TOP:
1277
case Base::BoundBox3f::FRONT:
1280
case Base::BoundBox3f::BACK:
1285
case Base::BoundBox3f::INVALID:
1290
GridElement pos(_ulX, _ulY, _ulZ);
1291
if (_cSearchPositions.find(pos) != _cSearchPositions.end()) {
1293
false; // grid element already visited => result from GetSideFromRay invalid
1297
if (_bValidRay && _rclGrid.CheckPos(_ulX, _ulY, _ulZ)) {
1298
GridElement pos(_ulX, _ulY, _ulZ);
1299
_cSearchPositions.insert(pos);
1300
raulElements.insert(raulElements.end(),
1301
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(),
1302
_rclGrid._aulGrid[_ulX][_ulY][_ulZ].end());
1305
_bValidRay = false; // Beam leaked