/*************************************************************************** * Copyright (c) 2015 Werner Mayer * * * * 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" #if defined(HAVE_PCL_OPENNURBS) #ifndef _PreComp_ # include # include # include # include # include # include #endif #include #include "BSplineFitting.h" #include #if PCL_VERSION_COMPARE(>=,1,7,0) # include # include # include # include # include #endif using namespace Reen; BSplineFitting::BSplineFitting(const std::vector& pts) : myPoints(pts) , myIterations(10) , myOrder(3) , myRefinement(4) , myInteriorSmoothness(0.2) , myInteriorWeight(1.0) , myBoundarySmoothness(0.2) , myBoundaryWeight(0.0) { } void BSplineFitting::setIterations(unsigned value) { myIterations = value; } void BSplineFitting::setOrder(unsigned value) { myOrder = value; } void BSplineFitting::setRefinement(unsigned value) { myRefinement = value; } void BSplineFitting::setInteriorSmoothness(double value) { myInteriorSmoothness = value; } void BSplineFitting::setInteriorWeight(double value) { myInteriorWeight = value; } void BSplineFitting::setBoundarySmoothness(double value) { myBoundarySmoothness = value; } void BSplineFitting::setBoundaryWeight(double value) { myBoundaryWeight = value; } Handle(Geom_BSplineSurface) BSplineFitting::perform() { #if PCL_VERSION_COMPARE(>=,1,7,0) pcl::on_nurbs::NurbsDataSurface data; for (std::vector::const_iterator it = myPoints.begin(); it != myPoints.end(); ++it) { if (!pcl_isnan (it->x) && !pcl_isnan (it->y) && !pcl_isnan (it->z)) data.interior.push_back (Eigen::Vector3d (it->x, it->y, it->z)); } // fit B-spline surface // pcl::on_nurbs::FittingSurface::Parameter params; params.interior_smoothness = myInteriorSmoothness; params.interior_weight = myInteriorWeight; params.boundary_smoothness = myBoundarySmoothness; params.boundary_weight = myBoundaryWeight; // initialize ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox (myOrder, &data); pcl::on_nurbs::FittingSurface fit (&data, nurbs); // fit.setQuiet (false); // enable/disable debug output // surface refinement for (unsigned i = 0; i < myRefinement; i++) { fit.refine(0); fit.refine(1); fit.assemble(params); fit.solve(); } // surface fitting with final refinement level for (unsigned i = 0; i < myIterations; i++) { fit.assemble(params); fit.solve(); } // fit B-spline curve #if 0 // parameters pcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params; curve_params.addCPsAccuracy = 5e-2; curve_params.addCPsIteration = 3; curve_params.maxCPs = 200; curve_params.accuracy = 1e-3; curve_params.iterations = 100; curve_params.param.closest_point_resolution = 0; curve_params.param.closest_point_weight = 1.0; curve_params.param.closest_point_sigma2 = 0.1; curve_params.param.interior_sigma2 = 0.00001; curve_params.param.smooth_concavity = 1.0; curve_params.param.smoothness = 1.0; // initialisation (circular) pcl::on_nurbs::NurbsDataCurve2d curve_data; curve_data.interior = data.interior_param; curve_data.interior_weight_function.push_back(true); ON_NurbsCurve curve_nurbs = pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D(order, curve_data.interior); // curve fitting pcl::on_nurbs::FittingCurve2dASDM curve_fit (&curve_data, curve_nurbs); // curve_fit.setQuiet (false); // enable/disable debug output curve_fit.fitting (curve_params); #endif // u parameters int numUKnots = fit.m_nurbs.KnotCount(0); int numUPoles = fit.m_nurbs.CVCount(0); int uDegree = fit.m_nurbs.Degree(0); bool uPeriodic = fit.m_nurbs.IsPeriodic(0) ? true : false; std::map uKnots; // v parameters int numVKnots = fit.m_nurbs.KnotCount(1); int numVPoles = fit.m_nurbs.CVCount(1); int vDegree = fit.m_nurbs.Degree(1); bool vPeriodic = fit.m_nurbs.IsPeriodic(1) ? true : false; std::map vKnots; TColgp_Array2OfPnt poles(1, numUPoles, 1, numVPoles); TColStd_Array2OfReal weights(1, numUPoles, 1, numVPoles); for (int i=0; i::iterator it = uKnots.find(value); if (it == uKnots.end()) uKnots[value] = 1; else it->second++; } vKnots[fit.m_nurbs.SuperfluousKnot(1,0)] = 1; vKnots[fit.m_nurbs.SuperfluousKnot(1,1)] = 1; for (int i=0; i::iterator it = vKnots.find(value); if (it == vKnots.end()) vKnots[value] = 1; else it->second++; } TColStd_Array1OfReal uKnotArray(1,uKnots.size()); TColStd_Array1OfInteger uMultArray(1,uKnots.size()); int index = 1; for (std::map::iterator it = uKnots.begin(); it != uKnots.end(); ++it, index++) { uKnotArray.SetValue(index, it->first); uMultArray.SetValue(index, it->second); } TColStd_Array1OfReal vKnotArray(1,vKnots.size()); TColStd_Array1OfInteger vMultArray(1,vKnots.size()); index = 1; for (std::map::iterator it = vKnots.begin(); it != vKnots.end(); ++it, index++) { vKnotArray.SetValue(index, it->first); vMultArray.SetValue(index, it->second); } Handle_Geom_BSplineSurface spline = new Geom_BSplineSurface(poles,weights, uKnotArray, vKnotArray, uMultArray, vMultArray, uDegree, vDegree, uPeriodic, vPeriodic); return spline; #else return Handle_Geom_BSplineSurface(); #endif } #endif // HAVE_PCL_OPENNURBS