FreeCAD

Форк
0
/
Visitor.cpp 
253 строки · 9.9 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2005 Imetric 3D GmbH                                    *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
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.      *
10
 *                                                                         *
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.                  *
15
 *                                                                         *
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                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#include "Algorithm.h"
26
#include "Approximation.h"
27
#include "MeshKernel.h"  // must be before Visitor.h
28
#include "Visitor.h"
29

30

31
using namespace MeshCore;
32

33

34
unsigned long MeshKernel::VisitNeighbourFacets(MeshFacetVisitor& rclFVisitor,
35
                                               FacetIndex ulStartFacet) const
36
{
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;
42

43
    if (ulStartFacet >= _aclFacetArray.size()) {
44
        return 0;
45
    }
46

47
    // pick up start point
48
    clCurrentLevel.push_back(ulStartFacet);
49
    _aclFacetArray[ulStartFacet].SetFlag(MeshFacet::VISIT);
50

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;
56

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
62
                }
63

64
                if (j >= ulCount) {
65
                    continue;  // error in data structure
66
                }
67

68
                clNBFacet = _aclFacetArray.begin() + j;
69

70
                if (!rclFVisitor.AllowVisit(*clNBFacet, *clCurrFacet, j, ulLevel, i)) {
71
                    continue;
72
                }
73
                if (clNBFacet->IsFlag(MeshFacet::VISIT)) {
74
                    continue;  // neighbour facet already visited
75
                }
76
                else {
77
                    // visit and mark
78
                    ulVisited++;
79
                    clNextLevel.push_back(j);
80
                    clNBFacet->SetFlag(MeshFacet::VISIT);
81
                    if (!rclFVisitor.Visit(*clNBFacet, *clCurrFacet, j, ulLevel)) {
82
                        return ulVisited;
83
                    }
84
                }
85
            }
86
        }
87

88
        clCurrentLevel = clNextLevel;
89
        clNextLevel.clear();
90
        ulLevel++;
91
    }
92

93
    return ulVisited;
94
}
95

96
unsigned long MeshKernel::VisitNeighbourFacetsOverCorners(MeshFacetVisitor& rclFVisitor,
97
                                                          FacetIndex ulStartFacet) const
98
{
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;
104

105
    if (ulStartFacet >= _aclFacetArray.size()) {
106
        return 0;
107
    }
108

109
    aclCurrentLevel.push_back(ulStartFacet);
110
    raclFAry[ulStartFacet].SetFlag(MeshFacet::VISIT);
111

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();
116
             ++pCurrFacet) {
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
123
                        ulVisited++;
124
                        FacetIndex ulFInd = pINb;
125
                        aclNextLevel.push_back(ulFInd);
126
                        pFBegin[pINb].SetFlag(MeshFacet::VISIT);
127
                        if (!rclFVisitor.Visit(pFBegin[pINb],
128
                                               raclFAry[*pCurrFacet],
129
                                               ulFInd,
130
                                               ulLevel)) {
131
                            return ulVisited;
132
                        }
133
                    }
134
                }
135
            }
136
        }
137
        aclCurrentLevel = aclNextLevel;
138
        aclNextLevel.clear();
139
        ulLevel++;
140
    }
141

142
    return ulVisited;
143
}
144

145
unsigned long MeshKernel::VisitNeighbourPoints(MeshPointVisitor& rclPVisitor,
146
                                               PointIndex ulStartPoint) const
147
{
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);
153

154
    aclCurrentLevel.push_back(ulStartPoint);
155
    (pPBegin + ulStartPoint)->SetFlag(MeshPoint::VISIT);
156

157
    while (!aclCurrentLevel.empty()) {
158
        // visit all neighbours of the current level
159
        for (clCurrIter = aclCurrentLevel.begin(); clCurrIter < aclCurrentLevel.end();
160
             ++clCurrIter) {
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
165
                    ulVisited++;
166
                    PointIndex ulPInd = pINb;
167
                    aclNextLevel.push_back(ulPInd);
168
                    pPBegin[pINb].SetFlag(MeshPoint::VISIT);
169
                    if (!rclPVisitor.Visit(pPBegin[pINb],
170
                                           *(pPBegin + (*clCurrIter)),
171
                                           ulPInd,
172
                                           ulLevel)) {
173
                        return ulVisited;
174
                    }
175
                }
176
            }
177
        }
178
        aclCurrentLevel = aclNextLevel;
179
        aclNextLevel.clear();
180
        ulLevel++;
181
    }
182

183
    return ulVisited;
184
}
185

186
// -------------------------------------------------------------------------
187

188
MeshSearchNeighbourFacetsVisitor::MeshSearchNeighbourFacetsVisitor(const MeshKernel& rclMesh,
189
                                                                   float fRadius,
190
                                                                   FacetIndex ulStartFacetIdx)
191
    : _rclMeshBase(rclMesh)
192
    , _clCenter(rclMesh.GetFacet(ulStartFacetIdx).GetGravityPoint())
193
    , _fRadius(fRadius)
194
{}
195

196
std::vector<FacetIndex> MeshSearchNeighbourFacetsVisitor::GetAndReset()
197
{
198
    MeshAlgorithm(_rclMeshBase).ResetFacetsFlag(_vecFacets, MeshFacet::VISIT);
199
    return _vecFacets;
200
}
201

202
// -------------------------------------------------------------------------
203

204
MeshPlaneVisitor::MeshPlaneVisitor(const MeshKernel& mesh,
205
                                   FacetIndex index,
206
                                   float deviation,
207
                                   std::vector<FacetIndex>& indices)
208
    : mesh(mesh)
209
    , indices(indices)
210
    , max_deviation(deviation)
211
    , fitter(new PlaneFit)
212
{
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]);
219
}
220

221
MeshPlaneVisitor::~MeshPlaneVisitor()
222
{
223
    delete fitter;
224
}
225

226
bool MeshPlaneVisitor::AllowVisit(const MeshFacet& face,
227
                                  const MeshFacet&,
228
                                  FacetIndex,
229
                                  unsigned long,
230
                                  unsigned short)
231
{
232
    if (!fitter->Done()) {
233
        fitter->Fit();
234
    }
235
    MeshGeomFacet triangle = mesh.GetFacet(face);
236
    for (const auto& pnt : triangle._aclPoints) {
237
        if (fabs(fitter->GetDistanceToPlane(pnt)) > max_deviation) {
238
            return false;
239
        }
240
    }
241
    return true;
242
}
243

244
bool MeshPlaneVisitor::Visit(const MeshFacet& face,
245
                             const MeshFacet&,
246
                             FacetIndex ulFInd,
247
                             unsigned long)
248
{
249
    MeshGeomFacet triangle = mesh.GetFacet(face);
250
    indices.push_back(ulFInd);
251
    fitter->AddPoint(triangle.GetGravityPoint());
252
    return true;
253
}
254

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.