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"
26
#include "Approximation.h"
27
#include "MeshKernel.h" // must be before Visitor.h
31
using namespace MeshCore;
34
unsigned long MeshKernel::VisitNeighbourFacets(MeshFacetVisitor& rclFVisitor,
35
FacetIndex ulStartFacet) const
37
unsigned long ulVisited = 0, ulLevel = 0;
38
unsigned long ulCount = _aclFacetArray.size();
39
std::vector<FacetIndex> clCurrentLevel, clNextLevel;
40
std::vector<FacetIndex>::iterator clCurrIter;
41
MeshFacetArray::_TConstIterator clCurrFacet, clNBFacet;
43
if (ulStartFacet >= _aclFacetArray.size()) {
47
// pick up start point
48
clCurrentLevel.push_back(ulStartFacet);
49
_aclFacetArray[ulStartFacet].SetFlag(MeshFacet::VISIT);
51
// as long as free neighbours
52
while (!clCurrentLevel.empty()) {
53
// visit all neighbours of the current level
54
for (clCurrIter = clCurrentLevel.begin(); clCurrIter < clCurrentLevel.end(); ++clCurrIter) {
55
clCurrFacet = _aclFacetArray.begin() + *clCurrIter;
57
// visit all neighbours of the current level if not yet done
58
for (unsigned short i = 0; i < 3; i++) {
59
auto j = clCurrFacet->_aulNeighbours[i]; // index to neighbour facet
60
if (j == FACET_INDEX_MAX) {
61
continue; // no neighbour facet
65
continue; // error in data structure
68
clNBFacet = _aclFacetArray.begin() + j;
70
if (!rclFVisitor.AllowVisit(*clNBFacet, *clCurrFacet, j, ulLevel, i)) {
73
if (clNBFacet->IsFlag(MeshFacet::VISIT)) {
74
continue; // neighbour facet already visited
79
clNextLevel.push_back(j);
80
clNBFacet->SetFlag(MeshFacet::VISIT);
81
if (!rclFVisitor.Visit(*clNBFacet, *clCurrFacet, j, ulLevel)) {
88
clCurrentLevel = clNextLevel;
96
unsigned long MeshKernel::VisitNeighbourFacetsOverCorners(MeshFacetVisitor& rclFVisitor,
97
FacetIndex ulStartFacet) const
99
unsigned long ulVisited = 0, ulLevel = 0;
100
MeshRefPointToFacets clRPF(*this);
101
const MeshFacetArray& raclFAry = _aclFacetArray;
102
MeshFacetArray::_TConstIterator pFBegin = raclFAry.begin();
103
std::vector<FacetIndex> aclCurrentLevel, aclNextLevel;
105
if (ulStartFacet >= _aclFacetArray.size()) {
109
aclCurrentLevel.push_back(ulStartFacet);
110
raclFAry[ulStartFacet].SetFlag(MeshFacet::VISIT);
112
while (!aclCurrentLevel.empty()) {
113
// visit all neighbours of the current level
114
for (std::vector<FacetIndex>::iterator pCurrFacet = aclCurrentLevel.begin();
115
pCurrFacet < aclCurrentLevel.end();
117
for (int i = 0; i < 3; i++) {
118
const MeshFacet& rclFacet = raclFAry[*pCurrFacet];
119
const std::set<FacetIndex>& raclNB = clRPF[rclFacet._aulPoints[i]];
120
for (FacetIndex pINb : raclNB) {
121
if (!pFBegin[pINb].IsFlag(MeshFacet::VISIT)) {
122
// only visit if VISIT Flag not set
124
FacetIndex ulFInd = pINb;
125
aclNextLevel.push_back(ulFInd);
126
pFBegin[pINb].SetFlag(MeshFacet::VISIT);
127
if (!rclFVisitor.Visit(pFBegin[pINb],
128
raclFAry[*pCurrFacet],
137
aclCurrentLevel = aclNextLevel;
138
aclNextLevel.clear();
145
unsigned long MeshKernel::VisitNeighbourPoints(MeshPointVisitor& rclPVisitor,
146
PointIndex ulStartPoint) const
148
unsigned long ulVisited = 0, ulLevel = 0;
149
std::vector<PointIndex> aclCurrentLevel, aclNextLevel;
150
std::vector<PointIndex>::iterator clCurrIter;
151
MeshPointArray::_TConstIterator pPBegin = _aclPointArray.begin();
152
MeshRefPointToPoints clNPs(*this);
154
aclCurrentLevel.push_back(ulStartPoint);
155
(pPBegin + ulStartPoint)->SetFlag(MeshPoint::VISIT);
157
while (!aclCurrentLevel.empty()) {
158
// visit all neighbours of the current level
159
for (clCurrIter = aclCurrentLevel.begin(); clCurrIter < aclCurrentLevel.end();
161
const std::set<PointIndex>& raclNB = clNPs[*clCurrIter];
162
for (PointIndex pINb : raclNB) {
163
if (!pPBegin[pINb].IsFlag(MeshPoint::VISIT)) {
164
// only visit if VISIT Flag not set
166
PointIndex ulPInd = pINb;
167
aclNextLevel.push_back(ulPInd);
168
pPBegin[pINb].SetFlag(MeshPoint::VISIT);
169
if (!rclPVisitor.Visit(pPBegin[pINb],
170
*(pPBegin + (*clCurrIter)),
178
aclCurrentLevel = aclNextLevel;
179
aclNextLevel.clear();
186
// -------------------------------------------------------------------------
188
MeshSearchNeighbourFacetsVisitor::MeshSearchNeighbourFacetsVisitor(const MeshKernel& rclMesh,
190
FacetIndex ulStartFacetIdx)
191
: _rclMeshBase(rclMesh)
192
, _clCenter(rclMesh.GetFacet(ulStartFacetIdx).GetGravityPoint())
196
std::vector<FacetIndex> MeshSearchNeighbourFacetsVisitor::GetAndReset()
198
MeshAlgorithm(_rclMeshBase).ResetFacetsFlag(_vecFacets, MeshFacet::VISIT);
202
// -------------------------------------------------------------------------
204
MeshPlaneVisitor::MeshPlaneVisitor(const MeshKernel& mesh,
207
std::vector<FacetIndex>& indices)
210
, max_deviation(deviation)
211
, fitter(new PlaneFit)
213
MeshGeomFacet triangle = mesh.GetFacet(index);
214
basepoint = triangle.GetGravityPoint();
215
normal = triangle.GetNormal();
216
fitter->AddPoint(triangle._aclPoints[0]);
217
fitter->AddPoint(triangle._aclPoints[1]);
218
fitter->AddPoint(triangle._aclPoints[2]);
221
MeshPlaneVisitor::~MeshPlaneVisitor()
226
bool MeshPlaneVisitor::AllowVisit(const MeshFacet& face,
232
if (!fitter->Done()) {
235
MeshGeomFacet triangle = mesh.GetFacet(face);
236
for (const auto& pnt : triangle._aclPoints) {
237
if (fabs(fitter->GetDistanceToPlane(pnt)) > max_deviation) {
244
bool MeshPlaneVisitor::Visit(const MeshFacet& face,
249
MeshGeomFacet triangle = mesh.GetFacet(face);
250
indices.push_back(ulFInd);
251
fitter->AddPoint(triangle.GetGravityPoint());