Download src/Mod/Mesh/App/Core/Grid.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 42.3 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Mesh/App/Core/Grid.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Mesh/App/Core/Grid.cpp
-
curl -L -o Grid.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Mesh/App/Core/Grid.cpp
42.3 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2005 Imetric 3D GmbH * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This library is free software; you can redistribute it and/or * | |
| * modify it under the terms of the GNU Library General Public * | |
| * License as published by the Free Software Foundation; either * | |
| * version 2 of the License, or (at your option) any later version. * | |
| * * | |
| * This library is distributed in the hope that it will be useful, * | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| * GNU Library General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Library General Public * | |
| * License along with this library; see the file COPYING.LIB. If not, * | |
| * write to the Free Software Foundation, Inc., 59 Temple Place, * | |
| * Suite 330, Boston, MA 02111-1307, USA * | |
| * * | |
| ***************************************************************************/ | |
| using namespace MeshCore; | |
| MeshGrid::MeshGrid(const MeshKernel& rclM) | |
| : _pclMesh(&rclM) | |
| , _ulCtElements(0) | |
| , _ulCtGridsX(0) | |
| , _ulCtGridsY(0) | |
| , _ulCtGridsZ(0) | |
| , _fGridLenX(0.0F) | |
| , _fGridLenY(0.0F) | |
| , _fGridLenZ(0.0F) | |
| , _fMinX(0.0F) | |
| , _fMinY(0.0F) | |
| , _fMinZ(0.0F) | |
| {} | |
| MeshGrid::MeshGrid() | |
| : _pclMesh(nullptr) | |
| , _ulCtElements(0) | |
| , _ulCtGridsX(MESH_CT_GRID) | |
| , _ulCtGridsY(MESH_CT_GRID) | |
| , _ulCtGridsZ(MESH_CT_GRID) | |
| , _fGridLenX(0.0F) | |
| , _fGridLenY(0.0F) | |
| , _fGridLenZ(0.0F) | |
| , _fMinX(0.0F) | |
| , _fMinY(0.0F) | |
| , _fMinZ(0.0F) | |
| {} | |
| void MeshGrid::Attach(const MeshKernel& rclM) | |
| { | |
| _pclMesh = &rclM; | |
| RebuildGrid(); | |
| } | |
| void MeshGrid::Clear() | |
| { | |
| _aulGrid.clear(); | |
| _pclMesh = nullptr; | |
| } | |
| void MeshGrid::Rebuild(unsigned long ulX, unsigned long ulY, unsigned long ulZ) | |
| { | |
| _ulCtGridsX = ulX; | |
| _ulCtGridsY = ulY; | |
| _ulCtGridsZ = ulZ; | |
| _ulCtElements = HasElements(); | |
| RebuildGrid(); | |
| } | |
| void MeshGrid::Rebuild(int iCtGridPerAxis) | |
| { | |
| _ulCtElements = HasElements(); | |
| CalculateGridLength(iCtGridPerAxis); | |
| RebuildGrid(); | |
| } | |
| void MeshGrid::InitGrid() | |
| { | |
| assert(_pclMesh); | |
| // Calculate grid length if not initialised | |
| // | |
| if ((_ulCtGridsX == 0) || (_ulCtGridsY == 0) || (_ulCtGridsZ == 0)) { | |
| CalculateGridLength(MESH_CT_GRID_PER_AXIS); | |
| } | |
| // Determine grid length and offset | |
| // | |
| { | |
| Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox(); | |
| float fLengthX = clBBMesh.LengthX(); | |
| float fLengthY = clBBMesh.LengthY(); | |
| float fLengthZ = clBBMesh.LengthZ(); | |
| { | |
| // Offset fGridLen/2 | |
| // | |
| _fGridLenX = (1.0F + fLengthX) / float(_ulCtGridsX); | |
| _fMinX = clBBMesh.MinX - 0.5F; | |
| } | |
| { | |
| _fGridLenY = (1.0F + fLengthY) / float(_ulCtGridsY); | |
| _fMinY = clBBMesh.MinY - 0.5F; | |
| } | |
| { | |
| _fGridLenZ = (1.0F + fLengthZ) / float(_ulCtGridsZ); | |
| _fMinZ = clBBMesh.MinZ - 0.5F; | |
| } | |
| } | |
| // Create data structure | |
| _aulGrid.clear(); | |
| _aulGrid.resize(_ulCtGridsX); | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| _aulGrid[i].resize(_ulCtGridsY); | |
| for (unsigned long j = 0; j < _ulCtGridsY; j++) { | |
| _aulGrid[i][j].resize(_ulCtGridsZ); | |
| } | |
| } | |
| } | |
| unsigned long MeshGrid::Inside( | |
| const Base::BoundBox3f& rclBB, | |
| std::vector<ElementIndex>& raulElements, | |
| bool bDelDoubles | |
| ) const | |
| { | |
| unsigned long ulMinX {}; | |
| unsigned long ulMinY {}; | |
| unsigned long ulMinZ {}; | |
| unsigned long ulMaxX {}; | |
| unsigned long ulMaxY {}; | |
| unsigned long ulMaxZ {}; | |
| raulElements.clear(); | |
| // Grid boxes for a more detailed selection | |
| Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ); | |
| Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ); | |
| for (auto i = ulMinX; i <= ulMaxX; i++) { | |
| for (auto j = ulMinY; j <= ulMaxY; j++) { | |
| for (auto k = ulMinZ; k <= ulMaxZ; k++) { | |
| raulElements | |
| .insert(raulElements.end(), _aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end()); | |
| } | |
| } | |
| } | |
| if (bDelDoubles) { | |
| // remove duplicate mentions | |
| std::sort(raulElements.begin(), raulElements.end()); | |
| raulElements.erase(std::unique(raulElements.begin(), raulElements.end()), raulElements.end()); | |
| } | |
| return raulElements.size(); | |
| } | |
| unsigned long MeshGrid::Inside( | |
| const Base::BoundBox3f& rclBB, | |
| std::vector<ElementIndex>& raulElements, | |
| const Base::Vector3f& rclOrg, | |
| float fMaxDist, | |
| bool bDelDoubles | |
| ) const | |
| { | |
| unsigned long ulMinX {}; | |
| unsigned long ulMinY {}; | |
| unsigned long ulMinZ {}; | |
| unsigned long ulMaxX {}; | |
| unsigned long ulMaxY {}; | |
| unsigned long ulMaxZ {}; | |
| float fGridDiag = GetBoundBox(0, 0, 0).CalcDiagonalLength(); | |
| float fMinDistP2 = (fGridDiag * fGridDiag) + (fMaxDist * fMaxDist); | |
| raulElements.clear(); | |
| // Grid boxes for a more detailed selection | |
| Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ); | |
| Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ); | |
| for (auto i = ulMinX; i <= ulMaxX; i++) { | |
| for (auto j = ulMinY; j <= ulMaxY; j++) { | |
| for (auto k = ulMinZ; k <= ulMaxZ; k++) { | |
| if (Base::DistanceP2(GetBoundBox(i, j, k).GetCenter(), rclOrg) < fMinDistP2) { | |
| raulElements.insert( | |
| raulElements.end(), | |
| _aulGrid[i][j][k].begin(), | |
| _aulGrid[i][j][k].end() | |
| ); | |
| } | |
| } | |
| } | |
| } | |
| if (bDelDoubles) { | |
| // remove duplicate mentions | |
| std::sort(raulElements.begin(), raulElements.end()); | |
| raulElements.erase(std::unique(raulElements.begin(), raulElements.end()), raulElements.end()); | |
| } | |
| return raulElements.size(); | |
| } | |
| unsigned long MeshGrid::Inside(const Base::BoundBox3f& rclBB, std::set<ElementIndex>& raulElements) const | |
| { | |
| unsigned long ulMinX {}; | |
| unsigned long ulMinY {}; | |
| unsigned long ulMinZ {}; | |
| unsigned long ulMaxX {}; | |
| unsigned long ulMaxY {}; | |
| unsigned long ulMaxZ {}; | |
| raulElements.clear(); | |
| // Grid boxes for a more detailed selection | |
| Position(Base::Vector3f(rclBB.MinX, rclBB.MinY, rclBB.MinZ), ulMinX, ulMinY, ulMinZ); | |
| Position(Base::Vector3f(rclBB.MaxX, rclBB.MaxY, rclBB.MaxZ), ulMaxX, ulMaxY, ulMaxZ); | |
| for (auto i = ulMinX; i <= ulMaxX; i++) { | |
| for (auto j = ulMinY; j <= ulMaxY; j++) { | |
| for (auto k = ulMinZ; k <= ulMaxZ; k++) { | |
| raulElements.insert(_aulGrid[i][j][k].begin(), _aulGrid[i][j][k].end()); | |
| } | |
| } | |
| } | |
| return raulElements.size(); | |
| } | |
| bool MeshGrid::CheckPosition( | |
| const Base::Vector3f& rclPoint, | |
| unsigned long& rulX, | |
| unsigned long& rulY, | |
| unsigned long& rulZ | |
| ) const | |
| { | |
| rulX = static_cast<unsigned long>((rclPoint.x - _fMinX) / _fGridLenX); | |
| rulY = static_cast<unsigned long>((rclPoint.y - _fMinY) / _fGridLenY); | |
| rulZ = static_cast<unsigned long>((rclPoint.z - _fMinZ) / _fGridLenZ); | |
| return ((rulX < _ulCtGridsX) && (rulY < _ulCtGridsY) && (rulZ < _ulCtGridsZ)); | |
| } | |
| void MeshGrid::Position( | |
| const Base::Vector3f& rclPoint, | |
| unsigned long& rulX, | |
| unsigned long& rulY, | |
| unsigned long& rulZ | |
| ) const | |
| { | |
| if (rclPoint.x <= _fMinX) { | |
| rulX = 0; | |
| } | |
| else { | |
| rulX = std::min<unsigned long>( | |
| static_cast<unsigned long>((rclPoint.x - _fMinX) / _fGridLenX), | |
| _ulCtGridsX - 1 | |
| ); | |
| } | |
| if (rclPoint.y <= _fMinY) { | |
| rulY = 0; | |
| } | |
| else { | |
| rulY = std::min<unsigned long>( | |
| static_cast<unsigned long>((rclPoint.y - _fMinY) / _fGridLenY), | |
| _ulCtGridsY - 1 | |
| ); | |
| } | |
| if (rclPoint.z <= _fMinZ) { | |
| rulZ = 0; | |
| } | |
| else { | |
| rulZ = std::min<unsigned long>( | |
| static_cast<unsigned long>((rclPoint.z - _fMinZ) / _fGridLenZ), | |
| _ulCtGridsZ - 1 | |
| ); | |
| } | |
| } | |
| void MeshGrid::CalculateGridLength(int iCtGridPerAxis) | |
| { | |
| // Calculate grid lengths or number of grids per dimension | |
| // There should be about 10 (?!?!) facets per grid | |
| // respectively max grids should not exceed 10000 | |
| Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox(); | |
| float fLenghtX = clBBMesh.LengthX(); | |
| float fLenghtY = clBBMesh.LengthY(); | |
| float fLenghtZ = clBBMesh.LengthZ(); | |
| float fLenghtD = clBBMesh.CalcDiagonalLength(); | |
| float fLengthTol = 0.05F * fLenghtD; | |
| bool bLenghtXisZero = (fLenghtX <= fLengthTol); | |
| bool bLenghtYisZero = (fLenghtY <= fLengthTol); | |
| bool bLenghtZisZero = (fLenghtZ <= fLengthTol); | |
| int iFlag = 0; | |
| int iMaxGrids = 1; | |
| if (bLenghtXisZero) { | |
| iFlag += 1; | |
| } | |
| else { | |
| iMaxGrids *= iCtGridPerAxis; | |
| } | |
| if (bLenghtYisZero) { | |
| iFlag += 2; | |
| } | |
| else { | |
| iMaxGrids *= iCtGridPerAxis; | |
| } | |
| if (bLenghtZisZero) { | |
| iFlag += 4; | |
| } | |
| else { | |
| iMaxGrids *= iCtGridPerAxis; | |
| } | |
| unsigned long ulGridsFacets = 10; | |
| float fFactorVolumen = 40.0; | |
| float fFactorArea = 10.0; | |
| switch (iFlag) { | |
| case 0: { | |
| float fVolumen = fLenghtX * fLenghtY * fLenghtZ; | |
| float fVolumenGrid = (fVolumen * ulGridsFacets) / (fFactorVolumen * _ulCtElements); | |
| if ((fVolumenGrid * iMaxGrids) < fVolumen) { | |
| fVolumenGrid = fVolumen / static_cast<float>(iMaxGrids); | |
| } | |
| float fLengthGrid = std::pow(fVolumenGrid, 1.0F / 3.0F); | |
| _ulCtGridsX = std::max(static_cast<unsigned long>(fLenghtX / fLengthGrid), 1UL); | |
| _ulCtGridsY = std::max(static_cast<unsigned long>(fLenghtY / fLengthGrid), 1UL); | |
| _ulCtGridsZ = std::max(static_cast<unsigned long>(fLenghtZ / fLengthGrid), 1UL); | |
| } break; | |
| case 1: { | |
| _ulCtGridsX = 1; // bLenghtXisZero | |
| float fArea = fLenghtY * fLenghtZ; | |
| float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements); | |
| if ((fAreaGrid * iMaxGrids) < fArea) { | |
| fAreaGrid = fArea / static_cast<float>(iMaxGrids); | |
| } | |
| auto fLengthGrid = float(std::sqrt(fAreaGrid)); | |
| _ulCtGridsY | |
| = std::max<unsigned long>(static_cast<unsigned long>(fLenghtY / fLengthGrid), 1); | |
| _ulCtGridsZ | |
| = std::max<unsigned long>(static_cast<unsigned long>(fLenghtZ / fLengthGrid), 1); | |
| } break; | |
| case 2: { | |
| _ulCtGridsY = 1; // bLenghtYisZero | |
| float fArea = fLenghtX * fLenghtZ; | |
| float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements); | |
| if ((fAreaGrid * iMaxGrids) < fArea) { | |
| fAreaGrid = fArea / static_cast<float>(iMaxGrids); | |
| } | |
| auto fLengthGrid = float(std::sqrt(fAreaGrid)); | |
| _ulCtGridsX | |
| = std::max<unsigned long>(static_cast<unsigned long>(fLenghtX / fLengthGrid), 1); | |
| _ulCtGridsZ | |
| = std::max<unsigned long>(static_cast<unsigned long>(fLenghtZ / fLengthGrid), 1); | |
| } break; | |
| case 3: { | |
| _ulCtGridsX = 1; // bLenghtXisZero | |
| _ulCtGridsY = 1; // bLenghtYisZero | |
| _ulCtGridsZ = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero | |
| } break; | |
| case 4: { | |
| _ulCtGridsZ = 1; // bLenghtZisZero | |
| float fArea = fLenghtX * fLenghtY; | |
| float fAreaGrid = (fArea * ulGridsFacets) / (fFactorArea * _ulCtElements); | |
| if ((fAreaGrid * iMaxGrids) < fArea) { | |
| fAreaGrid = fArea / static_cast<float>(iMaxGrids); | |
| } | |
| auto fLengthGrid = float(std::sqrt(fAreaGrid)); | |
| _ulCtGridsX | |
| = std::max<unsigned long>(static_cast<unsigned long>(fLenghtX / fLengthGrid), 1); | |
| _ulCtGridsY | |
| = std::max<unsigned long>(static_cast<unsigned long>(fLenghtY / fLengthGrid), 1); | |
| } break; | |
| case 5: { | |
| _ulCtGridsX = 1; // bLenghtXisZero | |
| _ulCtGridsZ = 1; // bLenghtZisZero | |
| _ulCtGridsY = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero | |
| } break; | |
| case 6: { | |
| _ulCtGridsY = 1; // bLenghtYisZero | |
| _ulCtGridsZ = 1; // bLenghtZisZero | |
| _ulCtGridsX = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero | |
| } break; | |
| case 7: { | |
| _ulCtGridsX = static_cast<unsigned long>(iMaxGrids); // bLenghtXisZero | |
| _ulCtGridsY = static_cast<unsigned long>(iMaxGrids); // bLenghtYisZero | |
| _ulCtGridsZ = static_cast<unsigned long>(iMaxGrids); // bLenghtZisZero | |
| } break; | |
| } | |
| } | |
| void MeshGrid::SearchNearestFromPoint(const Base::Vector3f& pnt, std::set<ElementIndex>& indices) const | |
| { | |
| indices.clear(); | |
| Base::BoundBox3f clBB = GetBoundBox(); | |
| if (clBB.IsInBox(pnt)) { // Point lies within | |
| unsigned long ulX {}; | |
| unsigned long ulY {}; | |
| unsigned long ulZ {}; | |
| Position(pnt, ulX, ulY, ulZ); | |
| // int nX = ulX, nY = ulY, nZ = ulZ; | |
| unsigned long ulMaxLevel | |
| = std::max<unsigned long>(_ulCtGridsX, std::max<unsigned long>(_ulCtGridsY, _ulCtGridsZ)); | |
| unsigned long ulLevel = 0; | |
| while (indices.empty() && ulLevel <= ulMaxLevel) { | |
| GetHull(ulX, ulY, ulZ, ulLevel++, indices); | |
| } | |
| GetHull(ulX, ulY, ulZ, ulLevel, indices); | |
| } | |
| else { // Point outside | |
| Base::BoundBox3f::SIDE tSide = clBB.GetSideFromRay(pnt, clBB.GetCenter() - pnt); | |
| switch (tSide) { | |
| case Base::BoundBox3f::RIGHT: { | |
| unsigned long nX = 0; | |
| while (indices.empty() && nX < _ulCtGridsX) { | |
| for (unsigned long i = 0; i < _ulCtGridsY; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| indices.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end()); | |
| } | |
| } | |
| nX++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::LEFT: { | |
| unsigned long nX = _ulCtGridsX - 1; | |
| while (indices.empty() && nX < _ulCtGridsX) { | |
| for (unsigned long i = 0; i < _ulCtGridsY; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| indices.insert(_aulGrid[nX][i][j].begin(), _aulGrid[nX][i][j].end()); | |
| } | |
| } | |
| nX++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::TOP: { | |
| unsigned long nY = 0; | |
| while (indices.empty() && nY < _ulCtGridsY) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| indices.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end()); | |
| } | |
| } | |
| nY++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::BOTTOM: { | |
| unsigned long nY = _ulCtGridsY - 1; | |
| while (indices.empty() && nY < _ulCtGridsY) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| indices.insert(_aulGrid[i][nY][j].begin(), _aulGrid[i][nY][j].end()); | |
| } | |
| } | |
| nY--; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::BACK: { | |
| unsigned long nZ = 0; | |
| while (indices.empty() && nZ < _ulCtGridsZ) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsY; j++) { | |
| indices.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end()); | |
| } | |
| } | |
| nZ++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::FRONT: { | |
| unsigned long nZ = _ulCtGridsZ - 1; | |
| while (indices.empty() && nZ < _ulCtGridsZ) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsY; j++) { | |
| indices.insert(_aulGrid[i][j][nZ].begin(), _aulGrid[i][j][nZ].end()); | |
| } | |
| } | |
| nZ--; | |
| } | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| } | |
| } | |
| void MeshGrid::GetHull( | |
| unsigned long ulX, | |
| unsigned long ulY, | |
| unsigned long ulZ, | |
| unsigned long ulDistance, | |
| std::set<ElementIndex>& raclInd | |
| ) const | |
| { | |
| int nX1 = std::max<int>(0, int(ulX) - int(ulDistance)); | |
| int nY1 = std::max<int>(0, int(ulY) - int(ulDistance)); | |
| int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance)); | |
| int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance)); | |
| int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance)); | |
| int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance)); | |
| // top plane | |
| for (int i = nX1; i <= nX2; i++) { | |
| for (int j = nY1; j <= nY2; j++) { | |
| GetElements( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| static_cast<unsigned long>(nZ1), | |
| raclInd | |
| ); | |
| } | |
| } | |
| // bottom plane | |
| for (int i = nX1; i <= nX2; i++) { | |
| for (int j = nY1; j <= nY2; j++) { | |
| GetElements( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| static_cast<unsigned long>(nZ2), | |
| raclInd | |
| ); | |
| } | |
| } | |
| // left plane | |
| for (int i = nY1; i <= nY2; i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| GetElements( | |
| static_cast<unsigned long>(nX1), | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| raclInd | |
| ); | |
| } | |
| } | |
| // right plane | |
| for (int i = nY1; i <= nY2; i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| GetElements( | |
| static_cast<unsigned long>(nX2), | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| raclInd | |
| ); | |
| } | |
| } | |
| // front plane | |
| for (int i = (nX1 + 1); i <= (nX2 - 1); i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| GetElements( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(nY1), | |
| static_cast<unsigned long>(j), | |
| raclInd | |
| ); | |
| } | |
| } | |
| // back plane | |
| for (int i = (nX1 + 1); i <= (nX2 - 1); i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| GetElements( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(nY2), | |
| static_cast<unsigned long>(j), | |
| raclInd | |
| ); | |
| } | |
| } | |
| } | |
| unsigned long MeshGrid::GetElements( | |
| unsigned long ulX, | |
| unsigned long ulY, | |
| unsigned long ulZ, | |
| std::set<ElementIndex>& raclInd | |
| ) const | |
| { | |
| const std::set<ElementIndex>& rclSet = _aulGrid[ulX][ulY][ulZ]; | |
| if (!rclSet.empty()) { | |
| raclInd.insert(rclSet.begin(), rclSet.end()); | |
| return rclSet.size(); | |
| } | |
| return 0; | |
| } | |
| unsigned long MeshGrid::GetElements( | |
| const Base::Vector3f& rclPoint, | |
| std::vector<ElementIndex>& aulFacets | |
| ) const | |
| { | |
| unsigned long ulX {}; | |
| unsigned long ulY {}; | |
| unsigned long ulZ {}; | |
| if (!CheckPosition(rclPoint, ulX, ulY, ulZ)) { | |
| return 0; | |
| } | |
| aulFacets.resize(_aulGrid[ulX][ulY][ulZ].size()); | |
| std::copy(_aulGrid[ulX][ulY][ulZ].begin(), _aulGrid[ulX][ulY][ulZ].end(), aulFacets.begin()); | |
| return aulFacets.size(); | |
| } | |
| unsigned long MeshGrid::GetIndexToPosition(unsigned long ulX, unsigned long ulY, unsigned long ulZ) const | |
| { | |
| if (!CheckPos(ulX, ulY, ulZ)) { | |
| return std::numeric_limits<unsigned long>::max(); | |
| } | |
| return (ulZ * _ulCtGridsY + ulY) * _ulCtGridsX + ulX; | |
| } | |
| bool MeshGrid::GetPositionToIndex( | |
| unsigned long id, | |
| unsigned long& ulX, | |
| unsigned long& ulY, | |
| unsigned long& ulZ | |
| ) const | |
| { | |
| ulX = id % _ulCtGridsX; | |
| ulY = (id / _ulCtGridsX) % _ulCtGridsY; | |
| ulZ = id / (_ulCtGridsX * _ulCtGridsY); | |
| if (!CheckPos(ulX, ulY, ulZ)) { | |
| ulX = std::numeric_limits<unsigned long>::max(); | |
| ulY = std::numeric_limits<unsigned long>::max(); | |
| ulZ = std::numeric_limits<unsigned long>::max(); | |
| return false; | |
| } | |
| return true; | |
| } | |
| // ---------------------------------------------------------------- | |
| MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM) | |
| : MeshGrid(rclM) | |
| { | |
| MeshFacetGrid::RebuildGrid(); | |
| } | |
| MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM, int iCtGridPerAxis) | |
| : MeshGrid(rclM) | |
| { | |
| Rebuild(iCtGridPerAxis); | |
| } | |
| MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM, unsigned long ulX, unsigned long ulY, unsigned long ulZ) | |
| : MeshGrid(rclM) | |
| { | |
| Rebuild(ulX, ulY, ulZ); | |
| } | |
| MeshFacetGrid::MeshFacetGrid(const MeshKernel& rclM, float fGridLen) | |
| : MeshGrid(rclM) | |
| { | |
| Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox(); | |
| Rebuild( | |
| std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthX() / fGridLen), 1), | |
| std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthY() / fGridLen), 1), | |
| std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthZ() / fGridLen), 1) | |
| ); | |
| } | |
| void MeshFacetGrid::Validate(const MeshKernel& rclMesh) | |
| { | |
| if (_pclMesh != &rclMesh) { | |
| Attach(rclMesh); | |
| } | |
| else if (rclMesh.CountFacets() != _ulCtElements) { | |
| RebuildGrid(); | |
| } | |
| } | |
| void MeshFacetGrid::Validate() | |
| { | |
| if (!_pclMesh) { | |
| return; | |
| } | |
| if (_pclMesh->CountFacets() != _ulCtElements) { | |
| RebuildGrid(); | |
| } | |
| } | |
| bool MeshFacetGrid::Verify() const | |
| { | |
| if (!_pclMesh) { | |
| return false; // no mesh attached | |
| } | |
| if (_pclMesh->CountFacets() != _ulCtElements) { | |
| return false; // not up-to-date | |
| } | |
| MeshGridIterator it(*this); | |
| MeshFacetIterator cF(*_pclMesh); | |
| for (it.Init(); it.More(); it.Next()) { | |
| std::vector<ElementIndex> aulElements; | |
| it.GetElements(aulElements); | |
| for (ElementIndex element : aulElements) { | |
| cF.Set(element); | |
| if (!cF->IntersectBoundingBox(it.GetBoundBox())) { | |
| return false; // no intersection between facet although the facet is in grid | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| void MeshFacetGrid::RebuildGrid() | |
| { | |
| _ulCtElements = _pclMesh->CountFacets(); | |
| InitGrid(); | |
| // Fill data structure | |
| MeshFacetIterator clFIter(*_pclMesh); | |
| unsigned long i = 0; | |
| for (clFIter.Init(); clFIter.More(); clFIter.Next()) { | |
| // AddFacet(*clFIter, i++, 2.0f); | |
| AddFacet(*clFIter, i++); | |
| } | |
| } | |
| unsigned long MeshFacetGrid::SearchNearestFromPoint(const Base::Vector3f& rclPt) const | |
| { | |
| ElementIndex ulFacetInd = ELEMENT_INDEX_MAX; | |
| float fMinDist = std::numeric_limits<float>::max(); | |
| Base::BoundBox3f clBB = GetBoundBox(); | |
| if (clBB.IsInBox(rclPt)) { // Point lies within | |
| unsigned long ulX {}; | |
| unsigned long ulY {}; | |
| unsigned long ulZ {}; | |
| Position(rclPt, ulX, ulY, ulZ); | |
| float fMinGridDist = std::min<float>(std::min<float>(_fGridLenX, _fGridLenY), _fGridLenZ); | |
| unsigned long ulDistance = 0; | |
| while (fMinDist > (fMinGridDist * float(ulDistance))) { | |
| SearchNearestFacetInHull(ulX, ulY, ulZ, ulDistance, rclPt, ulFacetInd, fMinDist); | |
| ulDistance++; | |
| } | |
| SearchNearestFacetInHull(ulX, ulY, ulZ, ulDistance, rclPt, ulFacetInd, fMinDist); | |
| } | |
| else { // Point outside | |
| Base::BoundBox3f::SIDE tSide = clBB.GetSideFromRay(rclPt, clBB.GetCenter() - rclPt); | |
| switch (tSide) { | |
| case Base::BoundBox3f::RIGHT: { | |
| unsigned long nX = 0; | |
| while ((fMinDist > ((clBB.MinX - rclPt.x) + (float(nX) * _fGridLenX))) | |
| && (nX < _ulCtGridsX)) { | |
| for (unsigned long i = 0; i < _ulCtGridsY; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| SearchNearestFacetInGrid(nX, i, j, rclPt, fMinDist, ulFacetInd); | |
| } | |
| } | |
| nX++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::LEFT: { | |
| unsigned long nX = _ulCtGridsX - 1; | |
| while ((fMinDist > ((rclPt.x - clBB.MinX) + (float(nX) * _fGridLenX))) | |
| && (nX < _ulCtGridsX)) { | |
| for (unsigned long i = 0; i < _ulCtGridsY; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| SearchNearestFacetInGrid(nX, i, j, rclPt, fMinDist, ulFacetInd); | |
| } | |
| } | |
| nX--; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::TOP: { | |
| unsigned long nY = 0; | |
| while ((fMinDist > ((clBB.MinY - rclPt.y) + (float(nY) * _fGridLenY))) | |
| && (nY < _ulCtGridsY)) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| SearchNearestFacetInGrid(i, nY, j, rclPt, fMinDist, ulFacetInd); | |
| } | |
| } | |
| nY++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::BOTTOM: { | |
| unsigned long nY = _ulCtGridsY - 1; | |
| while ((fMinDist > ((rclPt.y - clBB.MinY) + (float(nY) * _fGridLenY))) | |
| && (nY < _ulCtGridsY)) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsZ; j++) { | |
| SearchNearestFacetInGrid(i, nY, j, rclPt, fMinDist, ulFacetInd); | |
| } | |
| } | |
| nY--; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::BACK: { | |
| unsigned long nZ = 0; | |
| while ((fMinDist > ((clBB.MinZ - rclPt.z) + (float(nZ) * _fGridLenZ))) | |
| && (nZ < _ulCtGridsZ)) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsY; j++) { | |
| SearchNearestFacetInGrid(i, j, nZ, rclPt, fMinDist, ulFacetInd); | |
| } | |
| } | |
| nZ++; | |
| } | |
| break; | |
| } | |
| case Base::BoundBox3f::FRONT: { | |
| unsigned long nZ = _ulCtGridsZ - 1; | |
| while ((fMinDist > ((rclPt.z - clBB.MinZ) + (float(nZ) * _fGridLenZ))) | |
| && (nZ < _ulCtGridsZ)) { | |
| for (unsigned long i = 0; i < _ulCtGridsX; i++) { | |
| for (unsigned long j = 0; j < _ulCtGridsY; j++) { | |
| SearchNearestFacetInGrid(i, j, nZ, rclPt, fMinDist, ulFacetInd); | |
| } | |
| } | |
| nZ--; | |
| } | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| } | |
| return ulFacetInd; | |
| } | |
| unsigned long MeshFacetGrid::SearchNearestFromPoint(const Base::Vector3f& rclPt, float fMaxSearchArea) const | |
| { | |
| std::vector<ElementIndex> aulFacets; | |
| ElementIndex ulFacetInd = ELEMENT_INDEX_MAX; | |
| float fMinDist = fMaxSearchArea; | |
| MeshAlgorithm clFTool(*_pclMesh); | |
| Base::BoundBox3f clBB( | |
| rclPt.x - fMaxSearchArea, | |
| rclPt.y - fMaxSearchArea, | |
| rclPt.z - fMaxSearchArea, | |
| rclPt.x + fMaxSearchArea, | |
| rclPt.y + fMaxSearchArea, | |
| rclPt.z + fMaxSearchArea | |
| ); | |
| Inside(clBB, aulFacets, rclPt, fMaxSearchArea, true); | |
| for (ElementIndex facet : aulFacets) { | |
| float fDist {}; | |
| if (clFTool.Distance(rclPt, facet, fMinDist, fDist)) { | |
| fMinDist = fDist; | |
| ulFacetInd = facet; | |
| } | |
| } | |
| return ulFacetInd; | |
| } | |
| void MeshFacetGrid::SearchNearestFacetInHull( | |
| unsigned long ulX, | |
| unsigned long ulY, | |
| unsigned long ulZ, | |
| unsigned long ulDistance, | |
| const Base::Vector3f& rclPt, | |
| ElementIndex& rulFacetInd, | |
| float& rfMinDist | |
| ) const | |
| { | |
| int nX1 = std::max<int>(0, int(ulX) - int(ulDistance)); | |
| int nY1 = std::max<int>(0, int(ulY) - int(ulDistance)); | |
| int nZ1 = std::max<int>(0, int(ulZ) - int(ulDistance)); | |
| int nX2 = std::min<int>(int(_ulCtGridsX) - 1, int(ulX) + int(ulDistance)); | |
| int nY2 = std::min<int>(int(_ulCtGridsY) - 1, int(ulY) + int(ulDistance)); | |
| int nZ2 = std::min<int>(int(_ulCtGridsZ) - 1, int(ulZ) + int(ulDistance)); | |
| // top plane | |
| for (int i = nX1; i <= nX2; i++) { | |
| for (int j = nY1; j <= nY2; j++) { | |
| SearchNearestFacetInGrid( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| static_cast<unsigned long>(nZ1), | |
| rclPt, | |
| rfMinDist, | |
| rulFacetInd | |
| ); | |
| } | |
| } | |
| // bottom plane | |
| for (int i = nX1; i <= nX2; i++) { | |
| for (int j = nY1; j <= nY2; j++) { | |
| SearchNearestFacetInGrid( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| static_cast<unsigned long>(nZ2), | |
| rclPt, | |
| rfMinDist, | |
| rulFacetInd | |
| ); | |
| } | |
| } | |
| // left plane | |
| for (int i = nY1; i <= nY2; i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| SearchNearestFacetInGrid( | |
| static_cast<unsigned long>(nX1), | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| rclPt, | |
| rfMinDist, | |
| rulFacetInd | |
| ); | |
| } | |
| } | |
| // right plane | |
| for (int i = nY1; i <= nY2; i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| SearchNearestFacetInGrid( | |
| static_cast<unsigned long>(nX2), | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(j), | |
| rclPt, | |
| rfMinDist, | |
| rulFacetInd | |
| ); | |
| } | |
| } | |
| // front plane | |
| for (int i = (nX1 + 1); i <= (nX2 - 1); i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| SearchNearestFacetInGrid( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(nY1), | |
| static_cast<unsigned long>(j), | |
| rclPt, | |
| rfMinDist, | |
| rulFacetInd | |
| ); | |
| } | |
| } | |
| // back plane | |
| for (int i = (nX1 + 1); i <= (nX2 - 1); i++) { | |
| for (int j = (nZ1 + 1); j <= (nZ2 - 1); j++) { | |
| SearchNearestFacetInGrid( | |
| static_cast<unsigned long>(i), | |
| static_cast<unsigned long>(nY2), | |
| static_cast<unsigned long>(j), | |
| rclPt, | |
| rfMinDist, | |
| rulFacetInd | |
| ); | |
| } | |
| } | |
| } | |
| void MeshFacetGrid::SearchNearestFacetInGrid( | |
| unsigned long ulX, | |
| unsigned long ulY, | |
| unsigned long ulZ, | |
| const Base::Vector3f& rclPt, | |
| float& rfMinDist, | |
| ElementIndex& rulFacetInd | |
| ) const | |
| { | |
| const std::set<ElementIndex>& rclSet = _aulGrid[ulX][ulY][ulZ]; | |
| for (ElementIndex pI : rclSet) { | |
| float fDist = _pclMesh->GetFacet(pI).DistanceToPoint(rclPt); | |
| if (fDist < rfMinDist) { | |
| rfMinDist = fDist; | |
| rulFacetInd = pI; | |
| } | |
| } | |
| } | |
| //---------------------------------------------------------------------------- | |
| MeshPointGrid::MeshPointGrid(const MeshKernel& rclM) | |
| : MeshGrid(rclM) | |
| { | |
| MeshPointGrid::RebuildGrid(); | |
| } | |
| MeshPointGrid::MeshPointGrid() = default; | |
| MeshPointGrid::MeshPointGrid(const MeshKernel& rclM, unsigned long ulX, unsigned long ulY, unsigned long ulZ) | |
| : MeshGrid(rclM) | |
| { | |
| Rebuild(ulX, ulY, ulZ); | |
| } | |
| MeshPointGrid::MeshPointGrid(const MeshKernel& rclM, int iCtGridPerAxis) | |
| : MeshGrid(rclM) | |
| { | |
| Rebuild(iCtGridPerAxis); | |
| } | |
| MeshPointGrid::MeshPointGrid(const MeshKernel& rclM, float fGridLen) | |
| : MeshGrid(rclM) | |
| { | |
| Base::BoundBox3f clBBMesh = _pclMesh->GetBoundBox(); | |
| Rebuild( | |
| std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthX() / fGridLen), 1), | |
| std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthY() / fGridLen), 1), | |
| std::max<unsigned long>(static_cast<unsigned long>(clBBMesh.LengthZ() / fGridLen), 1) | |
| ); | |
| } | |
| void MeshPointGrid::AddPoint(const MeshPoint& rclPt, ElementIndex ulPtIndex, float fEpsilon) | |
| { | |
| (void)fEpsilon; | |
| unsigned long ulX {}; | |
| unsigned long ulY {}; | |
| unsigned long ulZ {}; | |
| Pos(Base::Vector3f(rclPt.x, rclPt.y, rclPt.z), ulX, ulY, ulZ); | |
| if ((ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ)) { | |
| _aulGrid[ulX][ulY][ulZ].insert(ulPtIndex); | |
| } | |
| } | |
| void MeshPointGrid::Validate(const MeshKernel& rclMesh) | |
| { | |
| if (_pclMesh != &rclMesh) { | |
| Attach(rclMesh); | |
| } | |
| else if (rclMesh.CountPoints() != _ulCtElements) { | |
| RebuildGrid(); | |
| } | |
| } | |
| void MeshPointGrid::Validate() | |
| { | |
| if (!_pclMesh) { | |
| return; | |
| } | |
| if (_pclMesh->CountPoints() != _ulCtElements) { | |
| RebuildGrid(); | |
| } | |
| } | |
| bool MeshPointGrid::Verify() const | |
| { | |
| if (!_pclMesh) { | |
| return false; // no mesh attached | |
| } | |
| if (_pclMesh->CountFacets() != _ulCtElements) { | |
| return false; // not up-to-date | |
| } | |
| MeshGridIterator it(*this); | |
| MeshPointIterator cP(*_pclMesh); | |
| for (it.Init(); it.More(); it.Next()) { | |
| std::vector<ElementIndex> aulElements; | |
| it.GetElements(aulElements); | |
| for (ElementIndex element : aulElements) { | |
| cP.Set(element); | |
| if (!it.GetBoundBox().IsInBox(*cP)) { | |
| return false; // point doesn't lie inside the grid element | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| void MeshPointGrid::RebuildGrid() | |
| { | |
| _ulCtElements = _pclMesh->CountPoints(); | |
| InitGrid(); | |
| // Fill data structure | |
| MeshPointIterator cPIter(*_pclMesh); | |
| unsigned long i = 0; | |
| for (cPIter.Init(); cPIter.More(); cPIter.Next()) { | |
| AddPoint(*cPIter, i++); | |
| } | |
| } | |
| void MeshPointGrid::Pos( | |
| const Base::Vector3f& rclPoint, | |
| unsigned long& rulX, | |
| unsigned long& rulY, | |
| unsigned long& rulZ | |
| ) const | |
| { | |
| rulX = static_cast<unsigned long>((rclPoint.x - _fMinX) / _fGridLenX); | |
| rulY = static_cast<unsigned long>((rclPoint.y - _fMinY) / _fGridLenY); | |
| rulZ = static_cast<unsigned long>((rclPoint.z - _fMinZ) / _fGridLenZ); | |
| } | |
| unsigned long MeshPointGrid::FindElements( | |
| const Base::Vector3f& rclPoint, | |
| std::set<ElementIndex>& aulElements | |
| ) const | |
| { | |
| unsigned long ulX {}; | |
| unsigned long ulY {}; | |
| unsigned long ulZ {}; | |
| Pos(rclPoint, ulX, ulY, ulZ); | |
| // check if the given point is inside the grid structure | |
| if ((ulX < _ulCtGridsX) && (ulY < _ulCtGridsY) && (ulZ < _ulCtGridsZ)) { | |
| return GetElements(ulX, ulY, ulZ, aulElements); | |
| } | |
| return 0; | |
| } | |
| // ---------------------------------------------------------------- | |
| MeshGridIterator::MeshGridIterator(const MeshGrid& rclG) | |
| : _rclGrid(rclG) | |
| , _clPt(0.0F, 0.0F, 0.0F) | |
| , _clDir(0.0F, 0.0F, 0.0F) | |
| {} | |
| bool MeshGridIterator::InitOnRay( | |
| const Base::Vector3f& rclPt, | |
| const Base::Vector3f& rclDir, | |
| float fMaxSearchArea, | |
| std::vector<ElementIndex>& raulElements | |
| ) | |
| { | |
| bool ret = InitOnRay(rclPt, rclDir, raulElements); | |
| _fMaxSearchArea = fMaxSearchArea; | |
| return ret; | |
| } | |
| bool MeshGridIterator::InitOnRay( | |
| const Base::Vector3f& rclPt, | |
| const Base::Vector3f& rclDir, | |
| std::vector<ElementIndex>& raulElements | |
| ) | |
| { | |
| // needed in NextOnRay() to avoid an infinite loop | |
| _cSearchPositions.clear(); | |
| _fMaxSearchArea = std::numeric_limits<float>::max(); | |
| raulElements.clear(); | |
| _clPt = rclPt; | |
| _clDir = rclDir; | |
| _bValidRay = false; | |
| // point lies within global BB | |
| if (_rclGrid.GetBoundBox().IsInBox(rclPt)) { // Determine the voxel by the starting point | |
| _rclGrid.Position(rclPt, _ulX, _ulY, _ulZ); | |
| raulElements.insert( | |
| raulElements.end(), | |
| _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), | |
| _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end() | |
| ); | |
| _bValidRay = true; | |
| } | |
| else { // Start point outside | |
| Base::Vector3f cP0; | |
| Base::Vector3f cP1; | |
| // determine the next point | |
| if (_rclGrid.GetBoundBox().IntersectWithLine(rclPt, rclDir, cP0, cP1)) { | |
| if ((cP0 - rclPt).Length() < (cP1 - rclPt).Length()) { | |
| _rclGrid.Position(cP0, _ulX, _ulY, _ulZ); | |
| } | |
| else { | |
| _rclGrid.Position(cP1, _ulX, _ulY, _ulZ); | |
| } | |
| raulElements.insert( | |
| raulElements.end(), | |
| _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), | |
| _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end() | |
| ); | |
| _bValidRay = true; | |
| } | |
| } | |
| return _bValidRay; | |
| } | |
| bool MeshGridIterator::NextOnRay(std::vector<ElementIndex>& raulElements) | |
| { | |
| if (!_bValidRay) { | |
| return false; // not initialized or beam exited | |
| } | |
| raulElements.clear(); | |
| Base::Vector3f clIntersectPoint; | |
| // Look for the next adjacent BB on the search beam | |
| Base::BoundBox3f::SIDE tSide | |
| = _rclGrid.GetBoundBox(_ulX, _ulY, _ulZ).GetSideFromRay(_clPt, _clDir, clIntersectPoint); | |
| // Search area | |
| // | |
| if ((_clPt - clIntersectPoint).Length() > _fMaxSearchArea) { | |
| _bValidRay = false; | |
| } | |
| else { | |
| switch (tSide) { | |
| case Base::BoundBox3f::LEFT: | |
| _ulX--; | |
| break; | |
| case Base::BoundBox3f::RIGHT: | |
| _ulX++; | |
| break; | |
| case Base::BoundBox3f::BOTTOM: | |
| _ulY--; | |
| break; | |
| case Base::BoundBox3f::TOP: | |
| _ulY++; | |
| break; | |
| case Base::BoundBox3f::FRONT: | |
| _ulZ--; | |
| break; | |
| case Base::BoundBox3f::BACK: | |
| _ulZ++; | |
| break; | |
| default: | |
| case Base::BoundBox3f::INVALID: | |
| _bValidRay = false; | |
| break; | |
| } | |
| GridElement pos(_ulX, _ulY, _ulZ); | |
| if (_cSearchPositions.find(pos) != _cSearchPositions.end()) { | |
| _bValidRay = false; // grid element already visited => result from GetSideFromRay invalid | |
| } | |
| } | |
| if (_bValidRay && _rclGrid.CheckPos(_ulX, _ulY, _ulZ)) { | |
| GridElement pos(_ulX, _ulY, _ulZ); | |
| _cSearchPositions.insert(pos); | |
| raulElements.insert( | |
| raulElements.end(), | |
| _rclGrid._aulGrid[_ulX][_ulY][_ulZ].begin(), | |
| _rclGrid._aulGrid[_ulX][_ulY][_ulZ].end() | |
| ); | |
| } | |
| else { | |
| _bValidRay = false; // Beam leaked | |
| } | |
| return _bValidRay; | |
| } | |