nurbs_tools.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 <iostream>
00039 #include <stdexcept>
00040 #include <map>
00041 #include <algorithm>
00042 #include <pcl/surface/on_nurbs/nurbs_tools.h>
00043 
00044 using namespace pcl;
00045 using namespace on_nurbs;
00046 using namespace Eigen;
00047 
00048 void
00049 NurbsTools::downsample_random (const vector_vec3d &data1, vector_vec3d &data2, unsigned size)
00050 {
00051   if (data1.size () <= size && size > 0)
00052   {
00053     data2 = data1;
00054     return;
00055   }
00056 
00057   unsigned s = unsigned (data1.size ());
00058   data2.clear ();
00059 
00060   for (unsigned i = 0; i < size; i++)
00061   {
00062     unsigned rnd = unsigned (s * (double (rand ()) / RAND_MAX));
00063     data2.push_back (data1[rnd]);
00064   }
00065 }
00066 
00067 void
00068 NurbsTools::downsample_random (vector_vec3d &data, unsigned size)
00069 {
00070   if (data.size () <= size && size > 0)
00071     return;
00072 
00073   unsigned s = unsigned (data.size ());
00074 
00075   vector_vec3d data_tmp;
00076 
00077   for (unsigned i = 0; i < size; i++)
00078   {
00079     unsigned rnd = unsigned ((s - 1) * (double (rand ()) / RAND_MAX));
00080     data_tmp.push_back (data[rnd]);
00081   }
00082 
00083   data = data_tmp;
00084 }
00085 
00086 //std::list<unsigned>
00087 //NurbsTools::getClosestPoints (const Eigen::Vector2d &p, const vector_vec2d &data, unsigned s)
00088 //{
00089 //  if (data.empty ())
00090 //    throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");
00091 //
00092 //  std::list<unsigned> idxs;
00093 //
00094 //  double dist2 (DBL_MAX);
00095 //  for (unsigned i = 0; i < data.size (); i++)
00096 //  {
00097 //    double d2 = (data[i] - p).squaredNorm ();
00098 //    if (d2 < dist2)
00099 //    {
00100 //      idxs.push_front (i);
00101 //      if (idxs.size () > s)
00102 //        idxs.pop_back ();
00103 //      dist2 = d2;
00104 //    }
00105 //  }
00106 //
00107 //  std::list<unsigned>::iterator it;
00108 //  printf ("NurbsTools::getClosestPoints");
00109 //  for (it = idxs.begin (); it != idxs.end (); it++)
00110 //  {
00111 //    printf (" %d", *it);
00112 //  }
00113 //  printf ("\n");
00114 //
00115 //  return idxs;
00116 //}
00117 
00118 unsigned
00119 NurbsTools::getClosestPoint (const Eigen::Vector2d &p, const vector_vec2d &data)
00120 {
00121   if (data.empty ())
00122     throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");
00123 
00124   unsigned idx (0);
00125   double dist2 (DBL_MAX);
00126   for (unsigned i = 0; i < data.size (); i++)
00127   {
00128     double d2 = (data[i] - p).squaredNorm ();
00129     if (d2 < dist2)
00130     {
00131       idx = i;
00132       dist2 = d2;
00133     }
00134   }
00135   return idx;
00136 }
00137 
00138 unsigned
00139 NurbsTools::getClosestPoint (const Eigen::Vector3d &p, const vector_vec3d &data)
00140 {
00141   if (data.empty ())
00142     throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");
00143 
00144   unsigned idx (0);
00145   double dist2 (DBL_MAX);
00146   for (unsigned i = 0; i < data.size (); i++)
00147   {
00148     double d2 = (data[i] - p).squaredNorm ();
00149     if (d2 < dist2)
00150     {
00151       idx = i;
00152       dist2 = d2;
00153     }
00154   }
00155   return idx;
00156 }
00157 
00158 unsigned
00159 NurbsTools::getClosestPoint (const Eigen::Vector2d &p, const Eigen::Vector2d &dir, const vector_vec2d &data,
00160                              unsigned &idxcp)
00161 {
00162   if (data.empty ())
00163     throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");
00164 
00165   unsigned idx (0);
00166   idxcp = 0;
00167   double dist2 (0.0);
00168   double dist2cp (DBL_MAX);
00169   for (unsigned i = 0; i < data.size (); i++)
00170   {
00171     Eigen::Vector2d v = (data[i] - p);
00172     double d2 = v.squaredNorm ();
00173 
00174     if (d2 < dist2cp)
00175     {
00176       idxcp = i;
00177       dist2cp = d2;
00178     }
00179 
00180     if (d2 == 0.0)
00181       return i;
00182 
00183     v.normalize ();
00184 
00185     double d1 = dir.dot (v);
00186     if (d1 / d2 > dist2)
00187     {
00188       idx = i;
00189       dist2 = d1 / d2;
00190     }
00191   }
00192   return idx;
00193 }
00194 
00195 Eigen::Vector3d
00196 NurbsTools::computeMean (const vector_vec3d &data)
00197 {
00198   Eigen::Vector3d u (0.0, 0.0, 0.0);
00199 
00200   unsigned s = unsigned (data.size ());
00201   double ds = 1.0 / s;
00202 
00203   for (unsigned i = 0; i < s; i++)
00204     u += (data[i] * ds);
00205 
00206   return u;
00207 }
00208 
00209 Eigen::Vector2d
00210 NurbsTools::computeMean (const vector_vec2d &data)
00211 {
00212   Eigen::Vector2d u (0.0, 0.0);
00213 
00214   size_t s = data.size ();
00215   double ds = 1.0 / double (s);
00216 
00217   for (size_t i = 0; i < s; i++)
00218     u += (data[i] * ds);
00219 
00220   return u;
00221 }
00222 
00223 Eigen::Vector3d
00224 NurbsTools::computeVariance (const Eigen::Vector3d &mean, const vector_vec3d &data)
00225 {
00226   Eigen::Vector3d var (0.0, 0.0, 0.0);
00227 
00228   size_t s = data.size ();
00229   double ds = 1.0 / double (s);
00230 
00231   for (size_t i = 0; i < s; i++)
00232   {
00233     Eigen::Vector3d v = data[i] - mean;
00234     var += Eigen::Vector3d (v (0) * v (0) * ds, v (1) * v (1) * ds, v (2) * v (2) * ds);
00235   }
00236 
00237   return var;
00238 }
00239 
00240 Eigen::Vector2d
00241 NurbsTools::computeVariance (const Eigen::Vector2d &mean, const vector_vec2d &data)
00242 {
00243   Eigen::Vector2d var (0.0, 0.0);
00244 
00245   size_t s = data.size ();
00246   double ds = 1.0 / double (s);
00247 
00248   for (size_t i = 0; i < s; i++)
00249   {
00250     Eigen::Vector2d v = data[i] - mean;
00251     var += Eigen::Vector2d (v (0) * v (0) * ds, v (1) * v (1) * ds);
00252   }
00253 
00254   return var;
00255 }
00256 
00257 void
00258 NurbsTools::computeBoundingBox (const ON_NurbsCurve &nurbs, Eigen::Vector3d &_min, Eigen::Vector3d &_max)
00259 {
00260   _min = Eigen::Vector3d (DBL_MAX, DBL_MAX, DBL_MAX);
00261   _max = Eigen::Vector3d (-DBL_MAX, -DBL_MAX, -DBL_MAX);
00262   for (int i = 0; i < nurbs.CVCount (); i++)
00263   {
00264     ON_3dPoint p;
00265     nurbs.GetCV (i, p);
00266 
00267     if (p.x < _min (0))
00268       _min (0) = p.x;
00269     if (p.y < _min (1))
00270       _min (1) = p.y;
00271     if (p.z < _min (2))
00272       _min (2) = p.z;
00273 
00274     if (p.x > _max (0))
00275       _max (0) = p.x;
00276     if (p.y > _max (1))
00277       _max (1) = p.y;
00278     if (p.z > _max (2))
00279       _max (2) = p.z;
00280   }
00281 }
00282 
00283 void
00284 NurbsTools::computeBoundingBox (const ON_NurbsSurface &nurbs, Eigen::Vector3d &_min, Eigen::Vector3d &_max)
00285 {
00286   _min = Eigen::Vector3d (DBL_MAX, DBL_MAX, DBL_MAX);
00287   _max = Eigen::Vector3d (-DBL_MAX, -DBL_MAX, -DBL_MAX);
00288   for (int i = 0; i < nurbs.CVCount (0); i++)
00289   {
00290     for (int j = 0; j < nurbs.CVCount (1); j++)
00291     {
00292       ON_3dPoint p;
00293       nurbs.GetCV (i, j, p);
00294 
00295       if (p.x < _min (0))
00296         _min (0) = p.x;
00297       if (p.y < _min (1))
00298         _min (1) = p.y;
00299       if (p.z < _min (2))
00300         _min (2) = p.z;
00301 
00302       if (p.x > _max (0))
00303         _max (0) = p.x;
00304       if (p.y > _max (1))
00305         _max (1) = p.y;
00306       if (p.z > _max (2))
00307         _max (2) = p.z;
00308     }
00309   }
00310 }
00311 
00312 double
00313 NurbsTools::computeRScale (const Eigen::Vector3d &_min, const Eigen::Vector3d &_max)
00314 {
00315   Eigen::Vector3d a = _max - _min;
00316 
00317   return std::max<double> (a (0), std::max<double> (a (1), a (2)));
00318 }
00319 
00320 void
00321 NurbsTools::pca (const vector_vec3d &data, Eigen::Vector3d &mean, Eigen::Matrix3d &eigenvectors,
00322                  Eigen::Vector3d &eigenvalues)
00323 {
00324   if (data.empty ())
00325   {
00326     printf ("[NurbsTools::pca] Error, data is empty\n");
00327     abort ();
00328   }
00329 
00330   mean = computeMean (data);
00331 
00332   unsigned s = unsigned (data.size ());
00333 
00334   Eigen::MatrixXd Q (3, s);
00335 
00336   for (unsigned i = 0; i < s; i++)
00337     Q.col (i) << (data[i] - mean);
00338 
00339   Eigen::Matrix3d C = Q * Q.transpose ();
00340 
00341   Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver (C);
00342   if (eigensolver.info () != Success)
00343   {
00344     printf ("[NurbsTools::pca] Can not find eigenvalues.\n");
00345     abort ();
00346   }
00347 
00348   for (int i = 0; i < 3; ++i)
00349   {
00350     eigenvalues (i) = eigensolver.eigenvalues () (2 - i);
00351     if (i == 2)
00352       eigenvectors.col (2) = eigenvectors.col (0).cross (eigenvectors.col (1));
00353     else
00354       eigenvectors.col (i) = eigensolver.eigenvectors ().col (2 - i);
00355   }
00356 }
00357 
00358 void
00359 NurbsTools::pca (const vector_vec2d &data, Eigen::Vector2d &mean, Eigen::Matrix2d &eigenvectors,
00360                  Eigen::Vector2d &eigenvalues)
00361 {
00362   if (data.empty ())
00363   {
00364     printf ("[NurbsTools::pca] Error, data is empty\n");
00365     abort ();
00366   }
00367 
00368   mean = computeMean (data);
00369 
00370   unsigned s = unsigned (data.size ());
00371 
00372   Eigen::MatrixXd Q (2, s);
00373 
00374   for (unsigned i = 0; i < s; i++)
00375     Q.col (i) << (data[i] - mean);
00376 
00377   Eigen::Matrix2d C = Q * Q.transpose ();
00378 
00379   Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver (C);
00380   if (eigensolver.info () != Success)
00381   {
00382     printf ("[NurbsTools::pca] Can not find eigenvalues.\n");
00383     abort ();
00384   }
00385 
00386   for (int i = 0; i < 2; ++i)
00387   {
00388     eigenvalues (i) = eigensolver.eigenvalues () (1 - i);
00389     eigenvectors.col (i) = eigensolver.eigenvectors ().col (1 - i);
00390   }
00391 }
00392 


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