FreeCAD

Форк
0
/
Points.cpp 
380 строк · 11.3 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de>              *
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
#ifndef _PreComp_
25
#include <QtConcurrentMap>
26
#include <boost/math/special_functions/fpclassify.hpp>
27
#include <cmath>
28
#include <iostream>
29
#endif
30

31
#include <Base/Matrix.h>
32
#include <Base/Stream.h>
33
#include <Base/Writer.h>
34

35
#include "Points.h"
36
#include "PointsAlgos.h"
37

38

39
#ifdef _MSC_VER
40
#include <ppl.h>
41
#endif
42

43
using namespace Points;
44
using namespace std;
45

46
TYPESYSTEM_SOURCE(Points::PointKernel, Data::ComplexGeoData)
47

48
PointKernel::PointKernel(const PointKernel& pts)
49
    : _Mtrx(pts._Mtrx)
50
    , _Points(pts._Points)
51
{}
52

53
PointKernel::PointKernel(PointKernel&& pts) noexcept
54
    : _Mtrx(pts._Mtrx)
55
    , _Points(std::move(pts._Points))
56
{}
57

58
std::vector<const char*> PointKernel::getElementTypes() const
59
{
60
    std::vector<const char*> temp;
61
    // temp.push_back("Segment");
62

63
    return temp;
64
}
65

66
unsigned long PointKernel::countSubElements(const char* /*Type*/) const
67
{
68
    return 0;
69
}
70

71
Data::Segment* PointKernel::getSubElement(const char* /*Type*/, unsigned long /*n*/) const
72
{
73
    // unsigned long i = 1;
74

75
    // if (strcmp(Type,"Segment") == 0) {
76
    //     // not implemented
77
    //     assert(0);
78
    //     return 0;
79
    // }
80

81
    return nullptr;
82
}
83

84
void PointKernel::transformGeometry(const Base::Matrix4D& rclMat)
85
{
86
    std::vector<value_type>& kernel = getBasicPoints();
87
#ifdef _MSC_VER
88
    // Win32-only at the moment since ppl.h is a Microsoft library. Points is not using Qt so we
89
    // cannot use QtConcurrent We could also rewrite Points to leverage SIMD instructions Other
90
    // option: openMP. But with VC2013 results in high CPU usage even after computation (busy-waits
91
    // for >100ms)
92
    Concurrency::parallel_for_each(kernel.begin(), kernel.end(), [rclMat](value_type& value) {
93
        value = rclMat * value;
94
    });
95
#else
96
    QtConcurrent::blockingMap(kernel, [rclMat](value_type& value) {
97
        rclMat.multVec(value, value);
98
    });
99
#endif
100
}
101

102
Base::BoundBox3d PointKernel::getBoundBox() const
103
{
104
    Base::BoundBox3d bnd;
105

106
#ifdef _MSC_VER
107
    // Thread-local bounding boxes
108
    Concurrency::combinable<Base::BoundBox3d> bbs;
109
    // Cannot use a const_point_iterator here as it is *not* a proper iterator (fails the for_each
110
    // template)
111
    Concurrency::parallel_for_each(_Points.begin(),
112
                                   _Points.end(),
113
                                   [this, &bbs](const value_type& value) {
114
                                       Base::Vector3d vertd(value.x, value.y, value.z);
115
                                       bbs.local().Add(this->_Mtrx * vertd);
116
                                   });
117
    // Combine each thread-local bounding box in the final bounding box
118
    bbs.combine_each([&bnd](const Base::BoundBox3d& lbb) {
119
        bnd.Add(lbb);
120
    });
121
#else
122
    for (const auto& it : *this) {
123
        bnd.Add(it);
124
    }
125
#endif
126
    return bnd;
127
}
128

129
PointKernel& PointKernel::operator=(const PointKernel& Kernel)
130
{
131
    if (this != &Kernel) {
132
        // copy the mesh structure
133
        setTransform(Kernel._Mtrx);
134
        this->_Points = Kernel._Points;
135
    }
136

137
    return *this;
138
}
139

140
PointKernel& PointKernel::operator=(PointKernel&& Kernel) noexcept
141
{
142
    if (this != &Kernel) {
143
        // copy the mesh structure
144
        setTransform(Kernel._Mtrx);
145
        this->_Points = std::move(Kernel._Points);
146
    }
147

148
    return *this;
149
}
150

151
unsigned int PointKernel::getMemSize() const
152
{
153
    return _Points.size() * sizeof(value_type);
154
}
155

156
PointKernel::size_type PointKernel::countValid() const
157
{
158
    size_type num = 0;
159
    for (const auto& it : *this) {
160
        if (!(boost::math::isnan(it.x) || boost::math::isnan(it.y) || boost::math::isnan(it.z))) {
161
            num++;
162
        }
163
    }
164
    return num;
165
}
166

167
std::vector<PointKernel::value_type> PointKernel::getValidPoints() const
168
{
169
    std::vector<PointKernel::value_type> valid;
170
    valid.reserve(countValid());
171
    for (const auto& it : *this) {
172
        if (!(boost::math::isnan(it.x) || boost::math::isnan(it.y) || boost::math::isnan(it.z))) {
173
            valid.emplace_back(static_cast<float_type>(it.x),
174
                               static_cast<float_type>(it.y),
175
                               static_cast<float_type>(it.z));
176
        }
177
    }
178
    return valid;
179
}
180

181
void PointKernel::Save(Base::Writer& writer) const
182
{
183
    if (!writer.isForceXML()) {
184
        writer.Stream() << writer.ind() << "<Points file=\""
185
                        << writer.addFile(writer.ObjectName.c_str(), this) << "\" "
186
                        << "mtrx=\"" << _Mtrx.toString() << "\"/>" << std::endl;
187
    }
188
}
189

190
void PointKernel::SaveDocFile(Base::Writer& writer) const
191
{
192
    Base::OutputStream str(writer.Stream());
193
    uint32_t uCt = (uint32_t)size();
194
    str << uCt;
195
    // store the data without transforming it
196
    for (const auto& pnt : _Points) {
197
        str << pnt.x << pnt.y << pnt.z;
198
    }
199
}
200

201
void PointKernel::Restore(Base::XMLReader& reader)
202
{
203
    clear();
204

205
    reader.readElement("Points");
206
    std::string file(reader.getAttribute("file"));
207

208
    if (!file.empty()) {
209
        // initiate a file read
210
        reader.addFile(file.c_str(), this);
211
    }
212
    if (reader.DocumentSchema > 3) {
213
        std::string Matrix(reader.getAttribute("mtrx"));
214
        _Mtrx.fromString(Matrix);
215
    }
216
}
217

218
void PointKernel::RestoreDocFile(Base::Reader& reader)
219
{
220
    Base::InputStream str(reader);
221
    uint32_t uCt = 0;
222
    str >> uCt;
223
    _Points.resize(uCt);
224
    for (unsigned long i = 0; i < uCt; i++) {
225
        float x {};
226
        float y {};
227
        float z {};
228
        str >> x >> y >> z;
229
        _Points[i].Set(x, y, z);
230
    }
231
}
232

233
void PointKernel::save(const char* file) const
234
{
235
    Base::ofstream out(Base::FileInfo(file), std::ios::out);
236
    save(out);
237
}
238

239
void PointKernel::load(const char* file)
240
{
241
    PointsAlgos::Load(*this, file);
242
}
243

244
void PointKernel::save(std::ostream& out) const
245
{
246
    out << "# ASCII" << std::endl;
247
    for (const auto& pnt : _Points) {
248
        out << pnt.x << " " << pnt.y << " " << pnt.z << std::endl;
249
    }
250
}
251

252
void PointKernel::getPoints(std::vector<Base::Vector3d>& Points,
253
                            std::vector<Base::Vector3d>& /*Normals*/,
254
                            double /*Accuracy*/,
255
                            uint16_t /*flags*/) const
256
{
257
    unsigned long ctpoints = _Points.size();
258
    Points.reserve(ctpoints);
259
    for (unsigned long i = 0; i < ctpoints; i++) {
260
        Points.push_back(this->getPoint(i));
261
    }
262
}
263

264
// ----------------------------------------------------------------------------
265

266
PointKernel::const_point_iterator::const_point_iterator(
267
    const PointKernel* kernel,
268
    std::vector<kernel_type>::const_iterator index)
269
    : _kernel(kernel)
270
    , _p_it(index)
271
{
272
    if (_p_it != kernel->_Points.end()) {
273
        value_type vertd(_p_it->x, _p_it->y, _p_it->z);
274
        this->_point = _kernel->_Mtrx * vertd;
275
    }
276
}
277

278
PointKernel::const_point_iterator::const_point_iterator(
279
    const PointKernel::const_point_iterator& fi) = default;
280

281
PointKernel::const_point_iterator::const_point_iterator(PointKernel::const_point_iterator&& fi) =
282
    default;
283

284
PointKernel::const_point_iterator::~const_point_iterator() = default;
285

286
PointKernel::const_point_iterator&
287
PointKernel::const_point_iterator::operator=(const PointKernel::const_point_iterator& pi) = default;
288

289
PointKernel::const_point_iterator&
290
PointKernel::const_point_iterator::operator=(PointKernel::const_point_iterator&& pi) = default;
291

292
void PointKernel::const_point_iterator::dereference()
293
{
294
    value_type vertd(_p_it->x, _p_it->y, _p_it->z);
295
    this->_point = _kernel->_Mtrx * vertd;
296
}
297

298
const PointKernel::const_point_iterator::value_type& PointKernel::const_point_iterator::operator*()
299
{
300
    dereference();
301
    return this->_point;
302
}
303

304
const PointKernel::const_point_iterator::value_type* PointKernel::const_point_iterator::operator->()
305
{
306
    dereference();
307
    return &(this->_point);
308
}
309

310
bool PointKernel::const_point_iterator::operator==(
311
    const PointKernel::const_point_iterator& pi) const
312
{
313
    return (this->_kernel == pi._kernel) && (this->_p_it == pi._p_it);
314
}
315

316
bool PointKernel::const_point_iterator::operator!=(
317
    const PointKernel::const_point_iterator& pi) const
318
{
319
    return !operator==(pi);
320
}
321

322
PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator++()
323
{
324
    ++(this->_p_it);
325
    return *this;
326
}
327

328
PointKernel::const_point_iterator PointKernel::const_point_iterator::operator++(int)
329
{
330
    PointKernel::const_point_iterator tmp = *this;
331
    ++(this->_p_it);
332
    return tmp;
333
}
334

335
PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator--()
336
{
337
    --(this->_p_it);
338
    return *this;
339
}
340

341
PointKernel::const_point_iterator PointKernel::const_point_iterator::operator--(int)
342
{
343
    PointKernel::const_point_iterator tmp = *this;
344
    --(this->_p_it);
345
    return tmp;
346
}
347

348
PointKernel::const_point_iterator
349
PointKernel::const_point_iterator::operator+(difference_type off) const
350
{
351
    PointKernel::const_point_iterator tmp = *this;
352
    return (tmp += off);
353
}
354

355
PointKernel::const_point_iterator
356
PointKernel::const_point_iterator::operator-(difference_type off) const
357
{
358
    PointKernel::const_point_iterator tmp = *this;
359
    return (tmp -= off);
360
}
361

362
PointKernel::const_point_iterator&
363
PointKernel::const_point_iterator::operator+=(difference_type off)
364
{
365
    (this->_p_it) += off;
366
    return *this;
367
}
368

369
PointKernel::const_point_iterator&
370
PointKernel::const_point_iterator::operator-=(difference_type off)
371
{
372
    (this->_p_it) -= off;
373
    return *this;
374
}
375

376
PointKernel::difference_type
377
PointKernel::const_point_iterator::operator-(const PointKernel::const_point_iterator& right) const
378
{
379
    return this->_p_it - right._p_it;
380
}
381

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

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

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

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