1
/***************************************************************************
2
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
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"
25
#include <QtConcurrentMap>
26
#include <boost/math/special_functions/fpclassify.hpp>
31
#include <Base/Matrix.h>
32
#include <Base/Stream.h>
33
#include <Base/Writer.h>
36
#include "PointsAlgos.h"
43
using namespace Points;
46
TYPESYSTEM_SOURCE(Points::PointKernel, Data::ComplexGeoData)
48
PointKernel::PointKernel(const PointKernel& pts)
50
, _Points(pts._Points)
53
PointKernel::PointKernel(PointKernel&& pts) noexcept
55
, _Points(std::move(pts._Points))
58
std::vector<const char*> PointKernel::getElementTypes() const
60
std::vector<const char*> temp;
61
// temp.push_back("Segment");
66
unsigned long PointKernel::countSubElements(const char* /*Type*/) const
71
Data::Segment* PointKernel::getSubElement(const char* /*Type*/, unsigned long /*n*/) const
73
// unsigned long i = 1;
75
// if (strcmp(Type,"Segment") == 0) {
84
void PointKernel::transformGeometry(const Base::Matrix4D& rclMat)
86
std::vector<value_type>& kernel = getBasicPoints();
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
92
Concurrency::parallel_for_each(kernel.begin(), kernel.end(), [rclMat](value_type& value) {
93
value = rclMat * value;
96
QtConcurrent::blockingMap(kernel, [rclMat](value_type& value) {
97
rclMat.multVec(value, value);
102
Base::BoundBox3d PointKernel::getBoundBox() const
104
Base::BoundBox3d bnd;
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
111
Concurrency::parallel_for_each(_Points.begin(),
113
[this, &bbs](const value_type& value) {
114
Base::Vector3d vertd(value.x, value.y, value.z);
115
bbs.local().Add(this->_Mtrx * vertd);
117
// Combine each thread-local bounding box in the final bounding box
118
bbs.combine_each([&bnd](const Base::BoundBox3d& lbb) {
122
for (const auto& it : *this) {
129
PointKernel& PointKernel::operator=(const PointKernel& Kernel)
131
if (this != &Kernel) {
132
// copy the mesh structure
133
setTransform(Kernel._Mtrx);
134
this->_Points = Kernel._Points;
140
PointKernel& PointKernel::operator=(PointKernel&& Kernel) noexcept
142
if (this != &Kernel) {
143
// copy the mesh structure
144
setTransform(Kernel._Mtrx);
145
this->_Points = std::move(Kernel._Points);
151
unsigned int PointKernel::getMemSize() const
153
return _Points.size() * sizeof(value_type);
156
PointKernel::size_type PointKernel::countValid() const
159
for (const auto& it : *this) {
160
if (!(boost::math::isnan(it.x) || boost::math::isnan(it.y) || boost::math::isnan(it.z))) {
167
std::vector<PointKernel::value_type> PointKernel::getValidPoints() const
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));
181
void PointKernel::Save(Base::Writer& writer) const
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;
190
void PointKernel::SaveDocFile(Base::Writer& writer) const
192
Base::OutputStream str(writer.Stream());
193
uint32_t uCt = (uint32_t)size();
195
// store the data without transforming it
196
for (const auto& pnt : _Points) {
197
str << pnt.x << pnt.y << pnt.z;
201
void PointKernel::Restore(Base::XMLReader& reader)
205
reader.readElement("Points");
206
std::string file(reader.getAttribute("file"));
209
// initiate a file read
210
reader.addFile(file.c_str(), this);
212
if (reader.DocumentSchema > 3) {
213
std::string Matrix(reader.getAttribute("mtrx"));
214
_Mtrx.fromString(Matrix);
218
void PointKernel::RestoreDocFile(Base::Reader& reader)
220
Base::InputStream str(reader);
224
for (unsigned long i = 0; i < uCt; i++) {
229
_Points[i].Set(x, y, z);
233
void PointKernel::save(const char* file) const
235
Base::ofstream out(Base::FileInfo(file), std::ios::out);
239
void PointKernel::load(const char* file)
241
PointsAlgos::Load(*this, file);
244
void PointKernel::save(std::ostream& out) const
246
out << "# ASCII" << std::endl;
247
for (const auto& pnt : _Points) {
248
out << pnt.x << " " << pnt.y << " " << pnt.z << std::endl;
252
void PointKernel::getPoints(std::vector<Base::Vector3d>& Points,
253
std::vector<Base::Vector3d>& /*Normals*/,
255
uint16_t /*flags*/) const
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));
264
// ----------------------------------------------------------------------------
266
PointKernel::const_point_iterator::const_point_iterator(
267
const PointKernel* kernel,
268
std::vector<kernel_type>::const_iterator index)
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;
278
PointKernel::const_point_iterator::const_point_iterator(
279
const PointKernel::const_point_iterator& fi) = default;
281
PointKernel::const_point_iterator::const_point_iterator(PointKernel::const_point_iterator&& fi) =
284
PointKernel::const_point_iterator::~const_point_iterator() = default;
286
PointKernel::const_point_iterator&
287
PointKernel::const_point_iterator::operator=(const PointKernel::const_point_iterator& pi) = default;
289
PointKernel::const_point_iterator&
290
PointKernel::const_point_iterator::operator=(PointKernel::const_point_iterator&& pi) = default;
292
void PointKernel::const_point_iterator::dereference()
294
value_type vertd(_p_it->x, _p_it->y, _p_it->z);
295
this->_point = _kernel->_Mtrx * vertd;
298
const PointKernel::const_point_iterator::value_type& PointKernel::const_point_iterator::operator*()
304
const PointKernel::const_point_iterator::value_type* PointKernel::const_point_iterator::operator->()
307
return &(this->_point);
310
bool PointKernel::const_point_iterator::operator==(
311
const PointKernel::const_point_iterator& pi) const
313
return (this->_kernel == pi._kernel) && (this->_p_it == pi._p_it);
316
bool PointKernel::const_point_iterator::operator!=(
317
const PointKernel::const_point_iterator& pi) const
319
return !operator==(pi);
322
PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator++()
328
PointKernel::const_point_iterator PointKernel::const_point_iterator::operator++(int)
330
PointKernel::const_point_iterator tmp = *this;
335
PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator--()
341
PointKernel::const_point_iterator PointKernel::const_point_iterator::operator--(int)
343
PointKernel::const_point_iterator tmp = *this;
348
PointKernel::const_point_iterator
349
PointKernel::const_point_iterator::operator+(difference_type off) const
351
PointKernel::const_point_iterator tmp = *this;
355
PointKernel::const_point_iterator
356
PointKernel::const_point_iterator::operator-(difference_type off) const
358
PointKernel::const_point_iterator tmp = *this;
362
PointKernel::const_point_iterator&
363
PointKernel::const_point_iterator::operator+=(difference_type off)
365
(this->_p_it) += off;
369
PointKernel::const_point_iterator&
370
PointKernel::const_point_iterator::operator-=(difference_type off)
372
(this->_p_it) -= off;
376
PointKernel::difference_type
377
PointKernel::const_point_iterator::operator-(const PointKernel::const_point_iterator& right) const
379
return this->_p_it - right._p_it;