00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
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