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
using namespace MeshCore;
34
MeshSearchNeighbours::MeshSearchNeighbours(const MeshKernel& rclM, float fSampleDistance)
36
, _rclFAry(rclM.GetFacets())
37
, _rclPAry(rclM.GetPoints())
39
, _fSampleDistance(fSampleDistance)
41
MeshAlgorithm(_rclMesh).ResetFacetFlag(MeshFacet::MARKED);
42
MeshAlgorithm(_rclMesh).ResetPointFlag(MeshPoint::MARKED);
45
void MeshSearchNeighbours::Reinit(float fSampleDistance)
47
_fSampleDistance = fSampleDistance;
48
MeshAlgorithm(_rclMesh).ResetFacetFlag(MeshFacet::MARKED);
49
MeshAlgorithm(_rclMesh).ResetPointFlag(MeshPoint::MARKED);
53
MeshSearchNeighbours::NeighboursFromFacet(FacetIndex ulFacetIdx,
55
unsigned long ulMinPoints,
56
std::vector<Base::Vector3f>& raclResultPoints)
58
bool bAddPoints = false;
60
_fMaxDistanceP2 = fDistance * fDistance;
61
_clCenter = _rclMesh.GetFacet(ulFacetIdx).GetGravityPoint();
63
unsigned long ulVisited = 1;
64
std::vector<MeshFacetArray::_TConstIterator> aclTestedFacet;
70
bool bFound = CheckDistToFacet(_rclFAry[ulFacetIdx]);
71
_rclFAry[ulFacetIdx].SetFlag(MeshFacet::MARKED);
72
aclTestedFacet.push_back(_rclFAry.begin() + ulFacetIdx);
74
if (!bFound && (_aclResult.size() < ulMinPoints)) {
76
bFound = ExpandRadius(ulMinPoints);
79
int nCtExpandRadius = 0;
80
// search neighbours, add not marked facets, test distance, add outer points
81
MeshFacetArray::_TConstIterator f_beg = _rclFAry.begin();
82
while (bFound && (nCtExpandRadius < 10)) {
85
std::set<PointIndex> aclTmp;
86
aclTmp.swap(_aclOuter);
87
for (PointIndex pI : aclTmp) {
88
const std::set<FacetIndex>& rclISet = _clPt2Fa[pI];
89
// search all facets hanging on this point
90
for (FacetIndex pJ : rclISet) {
91
const MeshFacet& rclF = f_beg[pJ];
93
if (!rclF.IsFlag(MeshFacet::MARKED)) {
94
bool bLF = CheckDistToFacet(rclF);
95
bFound = bFound || bLF;
96
rclF.SetFlag(MeshFacet::MARKED);
97
aclTestedFacet.push_back(f_beg + pJ);
100
ulVisited += rclISet.size();
103
// too few points inside radius found -> expand radius
104
if (!bFound && (_aclResult.size() < ulMinPoints)) {
107
bFound = ExpandRadius(ulMinPoints);
114
// reset marked facets, points
115
for (auto& pF : aclTestedFacet) {
116
pF->ResetFlag(MeshFacet::MARKED);
118
for (PointIndex pR : _aclResult) {
119
_rclPAry[pR].ResetFlag(MeshPoint::MARKED);
123
// copy points in result container
124
raclResultPoints.resize(_aclResult.size());
126
for (std::set<PointIndex>::iterator pI = _aclResult.begin(); pI != _aclResult.end();
128
raclResultPoints[i] = _rclPAry[*pI];
132
// sort points, remove points lying furthest from center
133
std::sort(raclResultPoints.begin(), raclResultPoints.end(), CDistRad(_clCenter));
134
raclResultPoints.erase(raclResultPoints.begin() + ulMinPoints, raclResultPoints.end());
140
void MeshSearchNeighbours::SampleAllFacets()
142
if (_aclSampledFacets.size() == _rclMesh.CountFacets()) {
143
return; // already sampled, do nothing
146
_aclSampledFacets.resize(_rclMesh.CountFacets());
147
MeshFacetIterator clFIter(_rclMesh);
149
for (clFIter.Init(); clFIter.More(); clFIter.Next(), i++) {
150
std::vector<Base::Vector3f> clPoints;
151
clFIter->SubSample(_fSampleDistance, clPoints);
152
_aclSampledFacets[i].resize(clPoints.size());
153
std::copy(clPoints.begin(), clPoints.end(), _aclSampledFacets[i].begin());
158
MeshSearchNeighbours::NeighboursFromSampledFacets(FacetIndex ulFacetIdx,
160
std::vector<Base::Vector3f>& raclResultPoints)
164
_fMaxDistanceP2 = fDistance * fDistance;
165
_clCenter = _rclMesh.GetFacet(ulFacetIdx).GetGravityPoint();
167
_akSphere.Center = Wm4::Vector3<float>(_clCenter.x, _clCenter.y, _clCenter.z);
168
_akSphere.Radius = fDistance;
170
unsigned long ulVisited = 1;
171
std::vector<MeshFacetArray::_TConstIterator> aclTestedFacet;
175
_aclPointsResult.clear();
178
bool bFound = AccumulateNeighbours(_rclFAry[ulFacetIdx], ulFacetIdx);
179
_rclFAry[ulFacetIdx].SetFlag(MeshFacet::MARKED);
181
// search neighbours, add not marked facets, test distance, add outer points
182
MeshFacetArray::_TConstIterator f_beg = _rclFAry.begin();
186
std::set<PointIndex> aclTmp;
187
aclTmp.swap(_aclOuter);
188
for (PointIndex pI : aclTmp) {
189
const std::set<FacetIndex>& rclISet = _clPt2Fa[pI];
190
// search all facets hanging on this point
191
for (FacetIndex pJ : rclISet) {
192
const MeshFacet& rclF = f_beg[pJ];
194
if (!rclF.IsFlag(MeshFacet::MARKED)) {
195
bool bLF = AccumulateNeighbours(rclF, pJ);
196
bFound = bFound || bLF;
197
rclF.SetFlag(MeshFacet::MARKED);
198
aclTestedFacet.push_back(f_beg + pJ);
201
ulVisited += rclISet.size();
205
// reset marked facets
206
for (auto& pF : aclTestedFacet) {
207
pF->ResetFlag(MeshFacet::MARKED);
210
// copy points in result container
211
raclResultPoints.resize(_aclPointsResult.size());
212
std::copy(_aclPointsResult.begin(), _aclPointsResult.end(), raclResultPoints.begin());
215
for (PointIndex pI : _aclResult) {
216
if (InnerPoint(_rclPAry[pI])) {
217
raclResultPoints.push_back(_rclPAry[pI]);
224
bool MeshSearchNeighbours::AccumulateNeighbours(const MeshFacet& rclF, FacetIndex ulFIdx)
228
for (PointIndex ulPIdx : rclF._aulPoints) {
229
_aclOuter.insert(ulPIdx);
230
_aclResult.insert(ulPIdx);
232
if (Base::DistanceP2(_clCenter, _rclPAry[ulPIdx]) < _fMaxDistanceP2) {
238
if (k == 3) { // add all sample points
239
_aclPointsResult.insert(_aclPointsResult.end(),
240
_aclSampledFacets[ulFIdx].begin(),
241
_aclSampledFacets[ulFIdx].end());
244
else { // add points inner radius
245
bFound = TriangleCutsSphere(rclF);
248
const std::vector<Base::Vector3f>& rclT = _aclSampledFacets[ulFIdx];
249
std::vector<Base::Vector3f> clTmp;
250
clTmp.reserve(rclT.size());
251
for (const auto& pI : rclT) {
252
if (InnerPoint(pI)) {
256
_aclPointsResult.insert(_aclPointsResult.end(), clTmp.begin(), clTmp.end());
263
bool MeshSearchNeighbours::ExpandRadius(unsigned long ulMinPoints)
265
// add facets from current level
266
_aclResult.insert(_aclOuter.begin(), _aclOuter.end());
267
for (PointIndex pI : _aclOuter) {
268
_rclPAry[pI].SetFlag(MeshPoint::MARKED);
271
if (_aclResult.size() < ulMinPoints) {
272
_fMaxDistanceP2 *= float(ulMinPoints) / float(_aclResult.size());
281
MeshSearchNeighbours::NeighboursFacetFromFacet(FacetIndex ulFacetIdx,
283
std::vector<Base::Vector3f>& raclResultPoints,
284
std::vector<FacetIndex>& raclResultFacets)
286
std::set<FacetIndex> aulFacetSet;
288
_fMaxDistanceP2 = fDistance * fDistance;
289
_clCenter = _rclMesh.GetFacet(ulFacetIdx).GetGravityPoint();
291
unsigned long ulVisited = 1;
292
std::vector<MeshFacetArray::_TConstIterator> aclTestedFacet;
298
bool bFound = CheckDistToFacet(_rclFAry[ulFacetIdx]);
299
_rclFAry[ulFacetIdx].SetFlag(MeshFacet::MARKED);
300
aclTestedFacet.push_back(_rclFAry.begin() + ulFacetIdx);
302
aulFacetSet.insert(ulFacetIdx);
304
// search neighbours, add not marked facets, test distance, add outer points
305
MeshFacetArray::_TConstIterator f_beg = _rclFAry.begin();
309
std::set<PointIndex> aclTmp;
310
aclTmp.swap(_aclOuter);
311
for (PointIndex pI : aclTmp) {
312
const std::set<FacetIndex>& rclISet = _clPt2Fa[pI];
313
// search all facets hanging on this point
314
for (FacetIndex pJ : rclISet) {
315
const MeshFacet& rclF = f_beg[pJ];
317
for (PointIndex ptIndex : rclF._aulPoints) {
318
if (Base::DistanceP2(_clCenter, _rclPAry[ptIndex]) < _fMaxDistanceP2) {
319
aulFacetSet.insert(pJ);
324
if (!rclF.IsFlag(MeshFacet::MARKED)) {
325
bool bLF = CheckDistToFacet(rclF);
327
bFound = bFound || bLF;
328
rclF.SetFlag(MeshFacet::MARKED);
329
aclTestedFacet.push_back(f_beg + pJ);
332
ulVisited += rclISet.size();
336
// reset marked facets, points
337
for (auto& pF : aclTestedFacet) {
338
pF->ResetFlag(MeshFacet::MARKED);
340
for (PointIndex pR : _aclResult) {
341
_rclPAry[pR].ResetFlag(MeshPoint::MARKED);
344
// copy points in result container
345
raclResultPoints.resize(_aclResult.size());
347
for (std::set<PointIndex>::iterator pI = _aclResult.begin(); pI != _aclResult.end();
349
raclResultPoints[i] = _rclPAry[*pI];
352
// copy facets in result container
353
raclResultFacets.insert(raclResultFacets.begin(), aulFacetSet.begin(), aulFacetSet.end());