sequential_fitter.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012-, Open Perception, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the copyright holder(s) nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * 
00035  *
00036  */
00037 
00038 #include <pcl/surface/on_nurbs/sequential_fitter.h>
00039 
00040 using namespace pcl;
00041 using namespace on_nurbs;
00042 using namespace Eigen;
00043 
00044 SequentialFitter::Parameter::Parameter (int order, int refinement, int iterationsQuad, int iterationsBoundary,
00045                                         int iterationsAdjust, int iterationsInterior, double forceBoundary,
00046                                         double forceBoundaryInside, double forceInterior, double stiffnessBoundary,
00047                                         double stiffnessInterior, int resolution)
00048 {
00049   this->order = order;
00050   this->refinement = refinement;
00051   this->iterationsQuad = iterationsQuad;
00052   this->iterationsBoundary = iterationsBoundary;
00053   this->iterationsAdjust = iterationsAdjust;
00054   this->iterationsInterior = iterationsInterior;
00055   this->forceBoundary = forceBoundary;
00056   this->forceBoundaryInside = forceBoundaryInside;
00057   this->forceInterior = forceInterior;
00058   this->stiffnessBoundary = stiffnessBoundary;
00059   this->stiffnessInterior = stiffnessInterior;
00060   this->resolution = resolution;
00061 }
00062 
00063 SequentialFitter::SequentialFitter (Parameter p)
00064 {
00065   this->m_params = p;
00066   this->m_have_cloud = false;
00067   this->m_have_corners = false;
00068   this->m_surf_id = -1;
00069 }
00070 
00071 void
00072 SequentialFitter::compute_quadfit ()
00073 {
00074   ON_NurbsSurface nurbs;
00075 
00076   if (m_have_corners)
00077   {
00078     nurbs = FittingSurface::initNurbs4Corners (2, m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
00079   }
00080   else
00081   {
00082     nurbs = FittingSurface::initNurbsPCA (2, &m_data);
00083     nurbs.GetCV (0, 0, m_corners[0]);
00084     nurbs.GetCV (1, 0, m_corners[1]);
00085     nurbs.GetCV (1, 1, m_corners[2]);
00086     nurbs.GetCV (0, 1, m_corners[3]);
00087     Eigen::Vector3d v0 (m_corners[0].x, m_corners[0].y, m_corners[0].z);
00088     Eigen::Vector3d v1 (m_corners[1].x, m_corners[1].y, m_corners[1].z);
00089     Eigen::Vector3d v2 (m_corners[2].x, m_corners[2].y, m_corners[2].z);
00090     Eigen::Vector3d v3 (m_corners[3].x, m_corners[3].y, m_corners[3].z);
00091     if (is_back_facing (v0, v1, v2, v3))
00092     {
00093       ON_3dPoint tmp[4];
00094       tmp[0] = m_corners[0];
00095       tmp[1] = m_corners[1];
00096       tmp[2] = m_corners[2];
00097       tmp[3] = m_corners[3];
00098       m_corners[3] = tmp[0];
00099       m_corners[2] = tmp[1];
00100       m_corners[1] = tmp[2];
00101       m_corners[0] = tmp[3];
00102       nurbs = FittingSurface::initNurbs4Corners (2, m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
00103     }
00104   }
00105 
00106   FittingSurface fitting (&m_data, nurbs);
00107 
00108   FittingSurface::Parameter paramFP (m_params.forceInterior, 1.0, 0.0, m_params.forceBoundary, 1.0, 0.0);
00109 
00110   // Quad fitting
00111   //  if( !m_quiet && m_dbgWin != NULL )
00112   //    NurbsConvertion::Nurbs2TomGine(m_dbgWin, *fitting->m_nurbs, m_surf_id, m_params.resolution);
00113   for (int r = 0; r < m_params.iterationsQuad; r++)
00114   {
00115     fitting.assemble (paramFP);
00116     fitting.solve ();
00117   }
00118   fitting.m_nurbs.GetCV (0, 0, m_corners[0]);
00119   fitting.m_nurbs.GetCV (1, 0, m_corners[1]);
00120   fitting.m_nurbs.GetCV (1, 1, m_corners[2]);
00121   fitting.m_nurbs.GetCV (0, 1, m_corners[3]);
00122 }
00123 
00124 void
00125 SequentialFitter::compute_refinement (FittingSurface* fitting)
00126 {
00127   // Refinement
00128   FittingSurface::Parameter paramFP (0.0, 1.0, 0.0, m_params.forceBoundary, m_params.stiffnessBoundary, 0.0);
00129 
00130   for (int r = 0; r < m_params.refinement; r++)
00131   {
00132     fitting->assemble (paramFP);
00133     fitting->solve ();
00134     fitting->refine (0);
00135     fitting->refine (1);
00136   }
00137 }
00138 
00139 void
00140 SequentialFitter::compute_boundary (FittingSurface* fitting)
00141 {
00142   FittingSurface::Parameter paramFP (0.0, 1.0, 0.0, m_params.forceBoundary, m_params.stiffnessBoundary, 0.0);
00143 
00144   // iterate boundary points
00145   for (int i = 0; i < m_params.iterationsBoundary; i++)
00146   {
00147     fitting->assemble (paramFP);
00148     fitting->solve ();
00149   }
00150 }
00151 void
00152 SequentialFitter::compute_interior (FittingSurface* fitting)
00153 {
00154   // iterate interior points
00155   //std::vector<double> wInt(m_data.interior.PointCount(), m_params.forceInterior);
00156   FittingSurface::Parameter paramFP (m_params.forceInterior, m_params.stiffnessInterior, 0.0, m_params.forceBoundary,
00157                                      m_params.stiffnessBoundary, 0.0);
00158 
00159   for (int i = 0; i < m_params.iterationsInterior; i++)
00160   {
00161     fitting->assemble (paramFP);
00162     //    fitting->assemble(wBnd, wInt, m_params.stiffnessBoundary, m_params.stiffnessInterior);
00163     fitting->solve ();
00164   }
00165 }
00166 
00167 Eigen::Vector2d
00168 SequentialFitter::project (const Eigen::Vector3d &pt)
00169 {
00170   Eigen::Vector4d pr (m_intrinsic * m_extrinsic * Eigen::Vector4d (pt (0), pt (1), pt (2), 1.0));
00171   pr (0) = pr (0) / pr (2);
00172   pr (1) = pr (1) / pr (2);
00173   if (pt.dot (Eigen::Vector3d (m_extrinsic (0, 2), m_extrinsic (1, 2), m_extrinsic (2, 2))) < 0.0f)
00174   { // avoids backprojection
00175     pr (0) = -pr (0);
00176     pr (1) = -pr (1);
00177   }
00178   return Eigen::Vector2d (pr (0), pr (1));
00179 }
00180 
00181 bool
00182 SequentialFitter::is_back_facing (const Eigen::Vector3d &v0, const Eigen::Vector3d &v1, const Eigen::Vector3d &v2,
00183                                   const Eigen::Vector3d &)
00184 {
00185   Eigen::Vector3d e1, e2, e3;
00186   e1 = v1 - v0;
00187   e2 = v2 - v0;
00188 
00189   Eigen::Vector3d z (m_extrinsic (0, 2), m_extrinsic (1, 2), m_extrinsic (2, 2));
00190   if (z.dot (e1.cross (e2)) > 0.0)
00191     return true;
00192   else
00193     return false;
00194 }
00195 
00196 /********************************************************************************/
00199 void
00200 SequentialFitter::setInputCloud (pcl::PointCloud<pcl::PointXYZRGB>::Ptr &pcl_cloud)
00201 {
00202   if (pcl_cloud.get () == 0 || pcl_cloud->points.size () == 0)
00203     throw std::runtime_error ("[SequentialFitter::setInputCloud] Error: Empty or invalid pcl-point-cloud.\n");
00204 
00205   m_cloud = pcl_cloud;
00206   m_have_cloud = true;
00207 }
00208 
00209 void
00210 SequentialFitter::setBoundary (pcl::PointIndices::Ptr &pcl_cloud_indexes)
00211 {
00212   if (m_cloud.get () == 0 || m_cloud->points.size () == 0)
00213     throw std::runtime_error ("[SequentialFitter::setBoundary] Error: Empty or invalid pcl-point-cloud.\n");
00214 
00215   this->m_boundary_indices = pcl_cloud_indexes;
00216   m_data.clear_boundary ();
00217   PCL2ON (m_cloud, pcl_cloud_indexes->indices, m_data.boundary);
00218 }
00219 
00220 void
00221 SequentialFitter::setInterior (pcl::PointIndices::Ptr &pcl_cloud_indexes)
00222 {
00223   if (m_cloud.get () == 0 || m_cloud->points.size () == 0)
00224     throw std::runtime_error ("[SequentialFitter::setIndices] Error: Empty or invalid pcl-point-cloud.\n");
00225 
00226   this->m_interior_indices = pcl_cloud_indexes;
00227   m_data.clear_interior ();
00228   PCL2ON (m_cloud, pcl_cloud_indexes->indices, m_data.interior);
00229 }
00230 
00231 void
00232 SequentialFitter::setCorners (pcl::PointIndices::Ptr &corners, bool flip_on_demand)
00233 {
00234   if (m_cloud.get () == 0 || m_cloud->points.size () == 0)
00235     throw std::runtime_error ("[SequentialFitter::setCorners] Error: Empty or invalid pcl-point-cloud.\n");
00236 
00237   if (corners->indices.size () < 4)
00238     throw std::runtime_error ("[SequentialFitter::setCorners] Error: to few corners (<4)\n");
00239 
00240   if (corners->indices.size () > 4)
00241     printf ("[SequentialFitter::setCorners] Warning: to many corners (>4)\n");
00242 
00243   bool flip = false;
00244   pcl::PointXYZRGB &pt0 = m_cloud->at (corners->indices[0]);
00245   pcl::PointXYZRGB &pt1 = m_cloud->at (corners->indices[1]);
00246   pcl::PointXYZRGB &pt2 = m_cloud->at (corners->indices[2]);
00247   pcl::PointXYZRGB &pt3 = m_cloud->at (corners->indices[3]);
00248 
00249   if (flip_on_demand)
00250   {
00251     Eigen::Vector3d v0 (pt0.x, pt0.y, pt0.z);
00252     Eigen::Vector3d v1 (pt1.x, pt1.y, pt1.z);
00253     Eigen::Vector3d v2 (pt2.x, pt2.y, pt2.z);
00254     Eigen::Vector3d v3 (pt3.x, pt3.y, pt3.z);
00255     flip = is_back_facing (v0, v1, v2, v3);
00256   }
00257 
00258   if (flip)
00259   {
00260     m_corners[3] = ON_3dPoint (pt0.x, pt0.y, pt0.z);
00261     m_corners[2] = ON_3dPoint (pt1.x, pt1.y, pt1.z);
00262     m_corners[1] = ON_3dPoint (pt2.x, pt2.y, pt2.z);
00263     m_corners[0] = ON_3dPoint (pt3.x, pt3.y, pt3.z);
00264   }
00265   else
00266   {
00267     m_corners[0] = ON_3dPoint (pt0.x, pt0.y, pt0.z);
00268     m_corners[1] = ON_3dPoint (pt1.x, pt1.y, pt1.z);
00269     m_corners[2] = ON_3dPoint (pt2.x, pt2.y, pt2.z);
00270     m_corners[3] = ON_3dPoint (pt3.x, pt3.y, pt3.z);
00271   }
00272 
00273   m_have_corners = true;
00274 }
00275 
00276 void
00277 SequentialFitter::setProjectionMatrix (
00278     const Eigen::Matrix4d &intrinsic, 
00279     const Eigen::Matrix4d &extrinsic)
00280 {
00281   m_intrinsic = intrinsic;
00282   m_extrinsic = extrinsic;
00283 }
00284 
00285 ON_NurbsSurface
00286 SequentialFitter::compute (bool assemble)
00287 {
00288   FittingSurface* fitting;
00289   ON_NurbsSurface nurbs;
00290   FittingSurface::Parameter paramFP (m_params.forceInterior, m_params.stiffnessInterior, 0.0, m_params.forceBoundary,
00291                                      m_params.stiffnessBoundary, 0.0);
00292 
00293   //  int surfid = -1;
00294   //  TomGine::tgRenderModel nurbs;
00295   //  TomGine::tgRenderModel box;
00296 
00297   if (m_data.boundary.size () > 0)
00298   {
00299     //    throw std::runtime_error("[SequentialFitter::compute] Error: empty boundary point-cloud.\n");
00300 
00301     compute_quadfit ();
00302 
00303     nurbs = FittingSurface::initNurbs4Corners (m_params.order, m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
00304     fitting = new FittingSurface (&m_data, nurbs);
00305     if (assemble)
00306       fitting->assemble (paramFP);
00307 
00308     compute_refinement (fitting);
00309 
00310     compute_boundary (fitting);
00311   }
00312   else
00313   {
00314     if (this->m_have_corners)
00315     {
00316       nurbs
00317           = FittingSurface::initNurbs4Corners (m_params.order, m_corners[0], m_corners[1], m_corners[2], m_corners[3]);
00318       fitting = new FittingSurface (&m_data, nurbs);
00319       if (assemble)
00320         fitting->assemble (paramFP);
00321     }
00322     else
00323     {
00324       fitting = new FittingSurface (m_params.order, &m_data);
00325       if (assemble)
00326         fitting->assemble (m_params.stiffnessInterior);
00327       int ncv0 = fitting->m_nurbs.m_cv_count[0];
00328       int ncv1 = fitting->m_nurbs.m_cv_count[1];
00329 
00330       fitting->m_nurbs.GetCV (0, 0, m_corners[0]);
00331       fitting->m_nurbs.GetCV (ncv0 - 1, 0, m_corners[1]);
00332       fitting->m_nurbs.GetCV (ncv0 - 1, ncv1 - 1, m_corners[2]);
00333       fitting->m_nurbs.GetCV (0, ncv1 - 1, m_corners[3]);
00334 
00335       Eigen::Vector3d v0 (m_corners[0].x, m_corners[0].y, m_corners[0].z);
00336       Eigen::Vector3d v1 (m_corners[1].x, m_corners[1].y, m_corners[1].z);
00337       Eigen::Vector3d v2 (m_corners[2].x, m_corners[2].y, m_corners[2].z);
00338       Eigen::Vector3d v3 (m_corners[3].x, m_corners[3].y, m_corners[3].z);
00339 
00340       if (is_back_facing (v0, v1, v2, v3))
00341       {
00342         ON_3dPoint tmp[4];
00343         tmp[0] = m_corners[0];
00344         tmp[1] = m_corners[1];
00345         tmp[2] = m_corners[2];
00346         tmp[3] = m_corners[3];
00347         m_corners[3] = tmp[0];
00348         m_corners[2] = tmp[1];
00349         m_corners[1] = tmp[2];
00350         m_corners[0] = tmp[3];
00351         delete (fitting);
00352         nurbs = FittingSurface::initNurbs4Corners (m_params.order, m_corners[0], m_corners[1], m_corners[2],
00353                                                    m_corners[3]);
00354         fitting = new FittingSurface (&m_data, nurbs);
00355         if (assemble)
00356           fitting->assemble (paramFP);
00357       }
00358 
00359       for (int r = 0; r < m_params.refinement; r++)
00360       {
00361         fitting->refine (0);
00362         fitting->refine (1);
00363       }
00364     }
00365   }
00366 
00367   if (m_data.interior.size () > 0)
00368     compute_interior (fitting);
00369 
00370   // update error
00371   fitting->assemble ();
00372 
00373   m_nurbs = fitting->m_nurbs;
00374 
00375   delete (fitting);
00376 
00377   return m_nurbs;
00378 }
00379 
00380 ON_NurbsSurface
00381 SequentialFitter::compute_boundary (const ON_NurbsSurface &nurbs)
00382 {
00383   if (m_data.boundary.size () <= 0)
00384   {
00385     printf ("[SequentialFitter::compute_boundary] Warning, no boundary points given: setBoundary()\n");
00386     return nurbs;
00387   }
00388 
00389   FittingSurface *fitting = new FittingSurface (&m_data, nurbs);
00390 
00391   this->compute_boundary (fitting);
00392 
00393   m_nurbs = fitting->m_nurbs;
00394 
00395   // update error
00396   fitting->assemble ();
00397 
00398   delete (fitting);
00399 
00400   return m_nurbs;
00401 }
00402 
00403 ON_NurbsSurface
00404 SequentialFitter::compute_interior (const ON_NurbsSurface &nurbs)
00405 {
00406   if (m_data.boundary.size () <= 0)
00407   {
00408     printf ("[SequentialFitter::compute_interior] Warning, no interior points given: setInterior()\n");
00409     return nurbs;
00410   }
00411   FittingSurface *fitting = new FittingSurface (&m_data, nurbs);
00412 
00413   this->compute_interior (fitting);
00414 
00415   // update error
00416   fitting->assemble ();
00417 
00418   m_nurbs = fitting->m_nurbs;
00419 
00420   delete (fitting);
00421 
00422   return m_nurbs;
00423 }
00424 
00425 void
00426 SequentialFitter::getInteriorError (std::vector<double> &error)
00427 {
00428   error = m_data.interior_error;
00429 }
00430 
00431 void
00432 SequentialFitter::getBoundaryError (std::vector<double> &error)
00433 {
00434   error = m_data.boundary_error;
00435 }
00436 
00437 void
00438 SequentialFitter::getInteriorParams (std::vector<Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d> > &params)
00439 {
00440   params = m_data.interior_param;
00441 }
00442 
00443 void
00444 SequentialFitter::getBoundaryParams (std::vector<Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d> > &params)
00445 {
00446   params = m_data.boundary_param;
00447 }
00448 
00449 void
00450 SequentialFitter::getInteriorNormals (std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > &normals)
00451 {
00452   normals = m_data.interior_normals;
00453 }
00454 
00455 void
00456 SequentialFitter::getBoundaryNormals (std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > &normals)
00457 {
00458   normals = m_data.boundary_normals;
00459 }
00460 
00461 void
00462 SequentialFitter::getClosestPointOnNurbs (
00463     ON_NurbsSurface nurbs, 
00464     const Eigen::Vector3d &pt, 
00465     Eigen::Vector2d& params,
00466     int maxSteps, 
00467     double accuracy)
00468 {
00469   Eigen::Vector3d p, tu, tv;
00470   double error;
00471 
00472   params = FittingSurface::findClosestElementMidPoint (nurbs, pt);
00473   params = FittingSurface::inverseMapping (nurbs, pt, params, error, p, tu, tv, maxSteps, accuracy);
00474 }
00475 
00476 ON_NurbsSurface
00477 SequentialFitter::grow (float max_dist, float max_angle, unsigned min_length, unsigned max_length)
00478 {
00479   unsigned num_bnd = unsigned (this->m_data.boundary_param.size ());
00480 
00481   if (num_bnd == 0)
00482     throw std::runtime_error ("[SequentialFitter::grow] No boundary given.");
00483 
00484   if (unsigned (this->m_data.boundary.size ()) != num_bnd)
00485   {
00486     printf ("[SequentialFitter::grow] %zu %u\n", this->m_data.boundary.size (), num_bnd);
00487     throw std::runtime_error ("[SequentialFitter::grow] size of boundary and boundary parameters do not match.");
00488   }
00489 
00490   if (this->m_boundary_indices->indices.size () != num_bnd)
00491   {
00492     printf ("[SequentialFitter::grow] %zu %u\n", this->m_boundary_indices->indices.size (), num_bnd);
00493     throw std::runtime_error ("[SequentialFitter::grow] size of boundary indices and boundary parameters do not match.");
00494   }
00495 
00496   float angle = cosf (max_angle);
00497   unsigned bnd_moved (0);
00498 
00499   for (unsigned i = 0; i < num_bnd; i++)
00500   {
00501     Eigen::Vector3d r, tu, tv, n, bn;
00502     double pointAndTangents[9];
00503     double u = this->m_data.boundary_param[i] (0);
00504     double v = this->m_data.boundary_param[i] (1);
00505 
00506     // Evaluate point and tangents
00507     m_nurbs.Evaluate (u, v, 1, 3, pointAndTangents);
00508     r (0) = pointAndTangents[0];
00509     r (1) = pointAndTangents[1];
00510     r (2) = pointAndTangents[2];
00511     tu (0) = pointAndTangents[3];
00512     tu (1) = pointAndTangents[4];
00513     tu (2) = pointAndTangents[5];
00514     tv (0) = pointAndTangents[6];
00515     tv (1) = pointAndTangents[7];
00516     tv (2) = pointAndTangents[8];
00517 
00518     n = tu.cross (tv);
00519     n.normalize ();
00520 
00521     // calculate boundary normal (pointing outward)
00522     double eps = 0.00000001;
00523 
00524     if (u < eps)
00525       bn = n.cross (tv);
00526     if (u > 1.0 - eps)
00527       bn = -n.cross (tv);
00528     if (v < eps)
00529       bn = -n.cross (tu);
00530     if (v > 1.0 - eps)
00531       bn = n.cross (tu);
00532 
00533     bn.normalize ();
00534 
00535     Eigen::Vector3d e (r (0) + bn (0) * max_dist, r (1) + bn (1) * max_dist, r (2) + bn (2) * max_dist);
00536 
00537     // Project into image plane
00538     Eigen::Vector2d ri = this->project (r);
00539     Eigen::Vector2d ei = this->project (e);
00540     Eigen::Vector2d bni = ei - ri;
00541     bni.normalize ();
00542 
00543     // search for valid points along boundary normal in image space
00544     float max_dist_sq = max_dist * max_dist;
00545     bool valid = false;
00546     pcl::PointXYZRGB point = m_cloud->at (this->m_boundary_indices->indices[i]);
00547     for (unsigned j = min_length; j < max_length; j++)
00548     {
00549       int col = int (ri (0) + bni (0) * j);
00550       int row = int (ri (1) + bni (1) * j);
00551 
00552       if (row >= int (m_cloud->height) || row < 0)
00553       {
00554         j = max_length;
00555         break;
00556       }
00557       if (col >= int (m_cloud->width) || col < 0)
00558       {
00559         j = max_length;
00560         break;
00561       }
00562 
00563       unsigned idx = row * m_cloud->width + col;
00564 
00565       pcl::PointXYZRGB &pt = m_cloud->at (idx);
00566       if (!pcl_isnan (pt.x) && !pcl_isnan (pt.y) && !pcl_isnan (pt.z))
00567       {
00568 
00569         // distance requirement
00570         Eigen::Vector3d d (pt.x - r (0), pt.y - r (1), pt.z - r (2));
00571         if (d.dot (d) < max_dist_sq)
00572         {
00573           d.normalize ();
00574           if (std::abs (d.dot (bn)) > (angle))
00575           {
00576             valid = true;
00577             point = pt;
00578           } // dot
00579         } // max_dist
00580       } // isnan
00581     } // j
00582 
00583     // if valid point found, add current boundary point to interior points and move boundary
00584     if (valid)
00585     {
00586       this->m_data.interior.push_back (this->m_data.boundary[i]);
00587       this->m_data.boundary[i] (0) = point.x;
00588       this->m_data.boundary[i] (1) = point.y;
00589       this->m_data.boundary[i] (2) = point.z;
00590       bnd_moved++;
00591     }
00592 
00593   } // i
00594 
00595   compute_interior (m_nurbs);
00596 
00597   double int_err (0.0);
00598   double div_err = 1.0 / double (m_data.interior_error.size ());
00599   for (unsigned i = 0; i < m_data.interior_error.size (); i++)
00600   {
00601     int_err += (m_data.interior_error[i] * div_err);
00602   }
00603 
00604   printf ("[SequentialFitter::grow] average interior error: %e\n", int_err);
00605 
00606   return m_nurbs;
00607 
00608 }
00609 
00610 unsigned
00611 SequentialFitter::PCL2ON (pcl::PointCloud<pcl::PointXYZRGB>::Ptr &pcl_cloud, const std::vector<int> &indices,
00612                           vector_vec3d &on_cloud)
00613 {
00614   unsigned numPoints (0);
00615 
00616   for (unsigned i = 0; i < indices.size (); i++)
00617   {
00618 
00619     pcl::PointXYZRGB &pt = pcl_cloud->at (indices[i]);
00620 
00621     if (!pcl_isnan (pt.x) && !pcl_isnan (pt.y) && !pcl_isnan (pt.z))
00622     {
00623       on_cloud.push_back (Eigen::Vector3d (pt.x, pt.y, pt.z));
00624       numPoints++;
00625     }
00626 
00627   }
00628 
00629   return numPoints;
00630 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:33:24