/*************************************************************************** * Copyright (c) 2011 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include #endif #include #include #include #include #include #include #include #include "Points.h" #include "PointsAlgos.h" #include "PointsPy.h" #ifdef _MSC_VER # include #endif using namespace Points; using namespace std; TYPESYSTEM_SOURCE(Points::PointKernel, Data::ComplexGeoData) PointKernel::PointKernel(const PointKernel& pts) : _Mtrx(pts._Mtrx) , _Points(pts._Points) { } std::vector PointKernel::getElementTypes() const { std::vector temp; //temp.push_back("Segment"); return temp; } unsigned long PointKernel::countSubElements(const char* /*Type*/) const { return 0; } Data::Segment* PointKernel::getSubElement(const char* /*Type*/, unsigned long /*n*/) const { //unsigned long i = 1; //if (strcmp(Type,"Segment") == 0) { // // not implemented // assert(0); // return 0; //} return nullptr; } void PointKernel::transformGeometry(const Base::Matrix4D &rclMat) { std::vector& kernel = getBasicPoints(); #ifdef _MSC_VER // Win32-only at the moment since ppl.h is a Microsoft library. Points is not using Qt so we cannot use QtConcurrent // We could also rewrite Points to leverage SIMD instructions // Other option: openMP. But with VC2013 results in high CPU usage even after computation (busy-waits for >100ms) Concurrency::parallel_for_each(kernel.begin(), kernel.end(), [rclMat](value_type& value) { value = rclMat * value; }); #else QtConcurrent::blockingMap(kernel, [rclMat](value_type& value) { rclMat.multVec(value, value); }); #endif } Base::BoundBox3d PointKernel::getBoundBox()const { Base::BoundBox3d bnd; #ifdef _MSC_VER // Thread-local bounding boxes Concurrency::combinable bbs; // Cannot use a const_point_iterator here as it is *not* a proper iterator (fails the for_each template) Concurrency::parallel_for_each(_Points.begin(), _Points.end(), [this, &bbs](const value_type& value) { Base::Vector3d vertd(value.x, value.y, value.z); bbs.local().Add(this->_Mtrx * vertd); }); // Combine each thread-local bounding box in the final bounding box bbs.combine_each([&bnd](const Base::BoundBox3d& lbb) { bnd.Add(lbb); }); #else for (const_point_iterator it = begin(); it != end(); ++it) bnd.Add(*it); #endif return bnd; } void PointKernel::operator = (const PointKernel& Kernel) { if (this != &Kernel) { // copy the mesh structure setTransform(Kernel._Mtrx); this->_Points = Kernel._Points; } } unsigned int PointKernel::getMemSize () const { return _Points.size() * sizeof(value_type); } PointKernel::size_type PointKernel::countValid() const { size_type num = 0; for (const_point_iterator it = begin(); it != end(); ++it) { if (!(boost::math::isnan(it->x) || boost::math::isnan(it->y) || boost::math::isnan(it->z))) num++; } return num; } std::vector PointKernel::getValidPoints() const { std::vector valid; valid.reserve(countValid()); for (const_point_iterator it = begin(); it != end(); ++it) { if (!(boost::math::isnan(it->x) || boost::math::isnan(it->y) || boost::math::isnan(it->z))) valid.emplace_back( static_cast(it->x), static_cast(it->y), static_cast(it->z)); } return valid; } void PointKernel::Save (Base::Writer &writer) const { if (!writer.isForceXML()) { writer.Stream() << writer.ind() << "" << std::endl; } } void PointKernel::SaveDocFile (Base::Writer &writer) const { Base::OutputStream str(writer.Stream()); uint32_t uCt = (uint32_t)size(); str << uCt; // store the data without transforming it for (std::vector::const_iterator it = _Points.begin(); it != _Points.end(); ++it) { str << it->x << it->y << it->z; } } void PointKernel::Restore(Base::XMLReader &reader) { clear(); reader.readElement("Points"); std::string file (reader.getAttribute("file") ); if (!file.empty()) { // initiate a file read reader.addFile(file.c_str(),this); } if (reader.DocumentSchema > 3) { std::string Matrix (reader.getAttribute("mtrx") ); _Mtrx.fromString(Matrix); } } void PointKernel::RestoreDocFile(Base::Reader &reader) { Base::InputStream str(reader); uint32_t uCt = 0; str >> uCt; _Points.resize(uCt); for (unsigned long i=0; i < uCt; i++) { float x, y, z; str >> x >> y >> z; _Points[i].Set(x,y,z); } } void PointKernel::save(const char* file) const { Base::ofstream out(file, std::ios::out); save(out); } void PointKernel::load(const char* file) { PointsAlgos::Load(*this,file); } void PointKernel::save(std::ostream& out) const { out << "# ASCII" << std::endl; for (std::vector::const_iterator it = _Points.begin(); it != _Points.end(); ++it) { out << it->x << " " << it->y << " " << it->z << std::endl; } } void PointKernel::getPoints(std::vector &Points, std::vector &/*Normals*/, float /*Accuracy*/, uint16_t /*flags*/) const { unsigned long ctpoints = _Points.size(); Points.reserve(ctpoints); for (unsigned long i=0; igetPoint(i)); } } // ---------------------------------------------------------------------------- PointKernel::const_point_iterator::const_point_iterator (const PointKernel* kernel, std::vector::const_iterator index) : _kernel(kernel), _p_it(index) { if(_p_it != kernel->_Points.end()) { value_type vertd(_p_it->x, _p_it->y, _p_it->z); this->_point = _kernel->_Mtrx * vertd; } } PointKernel::const_point_iterator::const_point_iterator (const PointKernel::const_point_iterator& fi) : _kernel(fi._kernel), _point(fi._point), _p_it(fi._p_it) { } //PointKernel::const_point_iterator::~const_point_iterator() //{ //} PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator=(const PointKernel::const_point_iterator& pi) { this->_kernel = pi._kernel; this->_point = pi._point; this->_p_it = pi._p_it; return *this; } void PointKernel::const_point_iterator::dereference() { value_type vertd(_p_it->x, _p_it->y, _p_it->z); this->_point = _kernel->_Mtrx * vertd; } const PointKernel::const_point_iterator::value_type& PointKernel::const_point_iterator::operator*() { dereference(); return this->_point; } const PointKernel::const_point_iterator::value_type* PointKernel::const_point_iterator::operator->() { dereference(); return &(this->_point); } bool PointKernel::const_point_iterator::operator==(const PointKernel::const_point_iterator& pi) const { return (this->_kernel == pi._kernel) && (this->_p_it == pi._p_it); } bool PointKernel::const_point_iterator::operator!=(const PointKernel::const_point_iterator& pi) const { return !operator==(pi); } PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator++() { ++(this->_p_it); return *this; } PointKernel::const_point_iterator PointKernel::const_point_iterator::operator++(int) { PointKernel::const_point_iterator tmp = *this; ++(this->_p_it); return tmp; } PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator--() { --(this->_p_it); return *this; } PointKernel::const_point_iterator PointKernel::const_point_iterator::operator--(int) { PointKernel::const_point_iterator tmp = *this; --(this->_p_it); return tmp; } PointKernel::const_point_iterator PointKernel::const_point_iterator::operator+ (difference_type off) const { PointKernel::const_point_iterator tmp = *this; return (tmp+=off); } PointKernel::const_point_iterator PointKernel::const_point_iterator::operator- (difference_type off) const { PointKernel::const_point_iterator tmp = *this; return (tmp-=off); } PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator+=(difference_type off) { (this->_p_it) += off; return *this; } PointKernel::const_point_iterator& PointKernel::const_point_iterator::operator-=(difference_type off) { (this->_p_it) -= off; return *this; } PointKernel::difference_type PointKernel::const_point_iterator::operator- (const PointKernel::const_point_iterator& right) const { return this->_p_it - right._p_it; }