closing_boundary.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/closing_boundary.h>
00039 
00040 using namespace pcl;
00041 using namespace on_nurbs;
00042 
00043 double
00044 ClosingBoundary::getLineDistance (const Eigen::Vector3d &P0, const Eigen::Vector3d &u, const Eigen::Vector3d &Q0,
00045                                   const Eigen::Vector3d &v, Eigen::Vector3d &P, Eigen::Vector3d &Q)
00046 {
00047   Eigen::Vector3d w0 = P0 - Q0;
00048 
00049   double a = u.dot (u);
00050   double b = u.dot (v);
00051   double c = v.dot (v);
00052   double d = u.dot (w0);
00053   double e = v.dot (w0);
00054 
00055   double s = (b * e - c * d) / (a * c - b * b);
00056   double t = (a * e - b * d) / (a * c - b * b);
00057 
00058   P = P0 + u * s;
00059   Q = Q0 + v * t;
00060 
00061   Eigen::Vector3d wc = P - Q;
00062   return wc.norm ();
00063 }
00064 
00065 Eigen::Vector3d
00066 ClosingBoundary::intersectPlanes (const Eigen::Vector3d &N1, double d1, const Eigen::Vector3d &N2, double d2,
00067                                   const Eigen::Vector3d &N3, double d3)
00068 {
00069   return (N2.cross (N3) * d1 + N3.cross (N1) * d2 + N1.cross (N2) * d3) / N1.dot (N2.cross (N3));
00070 }
00071 
00072 Eigen::Vector3d
00073 ClosingBoundary::commonBoundaryPoint1 (
00074     ON_NurbsSurface &n1, ON_NurbsSurface &n2, 
00075     Eigen::Vector2d &params1, Eigen::Vector2d &params2, 
00076     const Eigen::Vector3d &start, 
00077     unsigned nsteps, double &error, double accuracy)
00078 {
00079   Eigen::Vector3d current = start;
00080 
00081   double error1 (DBL_MAX);
00082   double error2 (DBL_MAX);
00083 
00084   Eigen::Vector3d p1, p2, tu1, tu2, tv1, tv2;
00085 
00086   params1 = FittingSurface::findClosestElementMidPoint (n1, current);
00087   params2 = FittingSurface::findClosestElementMidPoint (n2, current);
00088   params1 = FittingSurface::inverseMapping (n1, current, params1, error1, p1, tu1, tv1, nsteps, accuracy, true);
00089   params2 = FittingSurface::inverseMapping (n2, current, params2, error2, p2, tu2, tv2, nsteps, accuracy, true);
00090 
00091   for (unsigned i = 0; i < nsteps; i++)
00092   {
00093     params1 = FittingSurface::inverseMapping (n1, current, params1, error1, p1, tu1, tv1, nsteps, accuracy, true);
00094     params2 = FittingSurface::inverseMapping (n2, current, params2, error2, p2, tu2, tv2, nsteps, accuracy, true);
00095 
00096     //    dbgWin.AddLine3D(current(0), current(1), current(2), p1(0), p1(1), p1(2), 255, 0, 0);
00097     //    dbgWin.AddLine3D(current(0), current(1), current(2), p2(0), p2(1), p2(2), 255, 0, 0);
00098     //    dbgWin.AddPoint3D(current(0), current(1), current(2), 255, 0, 0, 3);
00099 
00100     current = (p1 + p2) * 0.5;
00101   }
00102 
00103   //  dbgWin.AddPoint3D(current(0), current(1), current(2), 255, 0, 255, 5);
00104   //  dbgWin.Update();
00105 
00106   error = 0.5 * (error1 + error2);
00107 
00108   return current;
00109 }
00110 
00111 Eigen::Vector3d
00112 ClosingBoundary::commonBoundaryPoint2 (
00113     ON_NurbsSurface &n1, ON_NurbsSurface &n2, 
00114     Eigen::Vector2d &params1, Eigen::Vector2d &params2, 
00115     const Eigen::Vector3d &start, 
00116     unsigned nsteps, double &error, double accuracy)
00117 {
00118   Eigen::Vector3d current = start;
00119 
00120   double error1 (DBL_MAX);
00121   double error2 (DBL_MAX);
00122 
00123   Eigen::Vector3d p1, p2, tu1, tu2, tv1, tv2;
00124 
00125   params1 = FittingSurface::findClosestElementMidPoint (n1, current);
00126   params2 = FittingSurface::findClosestElementMidPoint (n2, current);
00127   params1 = FittingSurface::inverseMapping (n1, current, params1, error1, p1, tu1, tv1, nsteps, accuracy, true);
00128   params2 = FittingSurface::inverseMapping (n2, current, params2, error2, p2, tu2, tv2, nsteps, accuracy, true);
00129 
00130   for (unsigned i = 0; i < nsteps; i++)
00131   {
00132     params1 = FittingSurface::inverseMapping (n1, current, params1, error1, p1, tu1, tv1, nsteps, accuracy, true);
00133     params2 = FittingSurface::inverseMapping (n2, current, params2, error2, p2, tu2, tv2, nsteps, accuracy, true);
00134 
00135     //    params1 = ntools1.inverseMappingBoundary(current, error1, p1, tu1, tv1, 10, 1e-2, true);
00136     //    params2 = ntools2.inverseMappingBoundary(current, error2, p2, tu2, tv2, 10, 1e-2, true);
00137 
00138     //    dbgWin.AddLine3D(current(0), current(1), current(2), p1(0), p1(1), p1(2), 0, 0, 255);
00139     //    dbgWin.AddLine3D(current(0), current(1), current(2), p2(0), p2(1), p2(2), 0, 0, 255);
00140     //    dbgWin.AddPoint3D(current(0), current(1), current(2), 0, 0, 255, 3);
00141 
00142     //    current = (p1 + p2) * 0.5;
00143     Eigen::Vector3d n1 = tu1.cross (tv1);
00144     n1.normalize ();
00145 
00146     Eigen::Vector3d n2 = tu2.cross (tv2);
00147     n2.normalize ();
00148 
00149     Eigen::Vector3d l1 = (p2 - n1 * n1.dot (p2 - p1)) - p1;
00150     l1.normalize ();
00151 
00152     Eigen::Vector3d l2 = (p1 - n2 * n2.dot (p1 - p2)) - p2;
00153     l2.normalize ();
00154 
00155     //        dbgWin.AddLine3D(p1(0), p1(1), p1(2), p1(0) + l1(0), p1(1) + l1(1), p1(2) + l1(2), 255, 0, 0);
00156     //        dbgWin.AddLine3D(p2(0), p2(1), p2(2), p2(0) + l2(0), p2(1) + l2(1), p2(2) + l2(2), 255, 0, 0);
00157 
00158     Eigen::Vector3d P, Q;
00159     getLineDistance (p1, l1, p2, l2, P, Q);
00160 
00161     current = (P + Q) * 0.5;
00162   }
00163 
00164   error = 0.5 * (error1 + error2);
00165 
00166   //  dbgWin.AddPoint3D(current(0), current(1), current(2), 255, 0, 255, 5);
00167   //  dbgWin.Update();
00168 
00169   return current;
00170 }
00171 
00172 Eigen::Vector3d
00173 ClosingBoundary::commonBoundaryPoint3 (
00174     ON_NurbsSurface &n1, ON_NurbsSurface &n2, 
00175     Eigen::Vector2d &params1, Eigen::Vector2d &params2, 
00176     const Eigen::Vector3d &start, 
00177     unsigned nsteps, double &error, double accuracy)
00178 {
00179   Eigen::Vector3d current = start;
00180 
00181   double error1 (DBL_MAX);
00182   double error2 (DBL_MAX);
00183 
00184   Eigen::Vector3d p1, p2, tu1, tu2, tv1, tv2;
00185 
00186   params1 = FittingSurface::findClosestElementMidPoint (n1, current);
00187   params2 = FittingSurface::findClosestElementMidPoint (n2, current);
00188   params1 = FittingSurface::inverseMapping (n1, current, params1, error1, p1, tu1, tv1, nsteps, accuracy, true);
00189   params2 = FittingSurface::inverseMapping (n2, current, params2, error2, p2, tu2, tv2, nsteps, accuracy, true);
00190 
00191   for (unsigned i = 0; i < nsteps; i++)
00192   {
00193     params1 = FittingSurface::inverseMapping (n1, current, params1, error1, p1, tu1, tv1, nsteps, accuracy, true);
00194     params2 = FittingSurface::inverseMapping (n2, current, params2, error2, p2, tu2, tv2, nsteps, accuracy, true);
00195 
00196     //    dbgWin.AddLine3D(current(0), current(1), current(2), p1(0), p1(1), p1(2), 0, 0, 255);
00197     //    dbgWin.AddLine3D(current(0), current(1), current(2), p2(0), p2(1), p2(2), 0, 0, 255);
00198     //    dbgWin.AddPoint3D(current(0), current(1), current(2), 0, 0, 255, 3);
00199 
00200     Eigen::Vector3d n1 = tu1.cross (tv1);
00201     n1.normalize ();
00202     double d1 = n1.dot (p1);
00203 
00204     Eigen::Vector3d n2 = tu2.cross (tv2);
00205     n2.normalize ();
00206     double d2 = n2.dot (p2);
00207 
00208     Eigen::Vector3d n3 = (p1 - current).cross (p2 - current);
00209     n3.normalize ();
00210     double d3 = n3.dot (current);
00211 
00212     current = intersectPlanes (n1, d1, n2, d2, n3, d3);
00213   }
00214 
00215   //  dbgWin.AddPoint3D(current(0), current(1), current(2), 255, 0, 255, 5);
00216   //  dbgWin.Update();
00217 
00218   error = 0.5 * (error1 + error2);
00219 
00220   return current;
00221 }
00222 
00223 void
00224 ClosingBoundary::sampleUniform (ON_NurbsSurface *nurbs, vector_vec3d &point_list, unsigned samples)
00225 {
00226   double ds = 1.0 / (samples - 1);
00227 
00228   double minU = nurbs->Knot (0, 0);
00229   double maxU = nurbs->Knot (0, nurbs->KnotCount (0) - 1);
00230   double minV = nurbs->Knot (1, 0);
00231   double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1);
00232 
00233   Eigen::Vector2d params;
00234   Eigen::Vector3d point;
00235 
00236   double points[3];
00237 
00238   for (unsigned j = 0; j < samples; j++)
00239   {
00240     params (1) = minV + (maxV - minV) * ds * j;
00241     for (unsigned i = 0; i < samples; i++)
00242     {
00243       params (0) = minU + (maxU - minU) * ds * i;
00244       nurbs->Evaluate (params (0), params (1), 0, 3, points);
00245       point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2]));
00246     }
00247   }
00248 }
00249 
00250 void
00251 ClosingBoundary::sampleRandom (ON_NurbsSurface *nurbs, vector_vec3d &point_list, unsigned samples)
00252 {
00253   double minU = nurbs->Knot (0, 0);
00254   double maxU = nurbs->Knot (0, nurbs->KnotCount (0) - 1);
00255   double minV = nurbs->Knot (1, 0);
00256   double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1);
00257 
00258   Eigen::Vector2d params;
00259   Eigen::Vector3d point;
00260 
00261   double points[3];
00262 
00263   for (unsigned i = 0; i < samples; i++)
00264   {
00265     params (0) = minU + (maxU - minU) * (double (rand ()) / RAND_MAX);
00266     params (1) = minV + (maxV - minV) * (double (rand ()) / RAND_MAX);
00267     nurbs->Evaluate (params (0), params (1), 0, 3, points);
00268     point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2]));
00269   }
00270 }
00271 
00272 void
00273 ClosingBoundary::sampleFromBoundary (ON_NurbsSurface *nurbs, vector_vec3d &point_list, vector_vec2d &param_list,
00274                                      unsigned samples)
00275 {
00276   double ds = 1.0 / (samples - 1);
00277 
00278   double minU = nurbs->Knot (0, 0);
00279   double maxU = nurbs->Knot (0, nurbs->KnotCount (0) - 1);
00280   double minV = nurbs->Knot (1, 0);
00281   double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1);
00282 
00283   Eigen::Vector2d params;
00284   Eigen::Vector3d point;
00285 
00286   double points[3];
00287 
00288   // WEST
00289   params (0) = minU;
00290   for (unsigned i = 0; i < samples; i++)
00291   {
00292     params (1) = minV + (maxV - minV) * ds * i;
00293     nurbs->Evaluate (params (0), params (1), 0, 3, points);
00294     point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2]));
00295     param_list.push_back (params);
00296   }
00297 
00298   // EAST
00299   params (0) = maxU;
00300   for (unsigned i = 0; i < samples; i++)
00301   {
00302     params (1) = minV + (maxV - minV) * ds * i;
00303     nurbs->Evaluate (params (0), params (1), 0, 3, points);
00304     point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2]));
00305     param_list.push_back (params);
00306   }
00307 
00308   // SOUTH
00309   params (1) = minV;
00310   for (unsigned i = 0; i < samples; i++)
00311   {
00312     params (0) = minU + (maxU - minU) * ds * i;
00313     nurbs->Evaluate (params (0), params (1), 0, 3, points);
00314     point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2]));
00315     param_list.push_back (params);
00316   }
00317 
00318   // NORTH
00319   params (1) = maxV;
00320   for (unsigned i = 0; i < samples; i++)
00321   {
00322     params (0) = minU + (maxU - minU) * ds * i;
00323     nurbs->Evaluate (params (0), params (1), 0, 3, points);
00324     point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2]));
00325     param_list.push_back (params);
00326   }
00327 }
00328 
00329 void
00330 ClosingBoundary::optimizeBoundary (std::vector<ON_NurbsSurface> &nurbs_list, std::vector<NurbsDataSurface> &data_list,
00331                                    Parameter param)
00332 {
00333   for (unsigned n1 = 0; n1 < nurbs_list.size (); n1++)
00334     data_list[n1].clear_boundary ();
00335 
00336   // for each nurbs
00337   for (unsigned n1 = 0; n1 < nurbs_list.size (); n1++)
00338   {
00339     //  for (unsigned n1 = 0; n1 < 1; n1++) {
00340     ON_NurbsSurface *nurbs1 = &nurbs_list[n1];
00341 
00342     // sample point list from nurbs1
00343     vector_vec3d boundary1;
00344     vector_vec2d params1;
00345     sampleFromBoundary (nurbs1, boundary1, params1, param.samples);
00346 
00347     // for each other nurbs
00348     for (unsigned n2 = (n1 + 1); n2 < nurbs_list.size (); n2++)
00349     {
00350       ON_NurbsSurface *nurbs2 = &nurbs_list[n2];
00351 
00352       // for all points in the point list
00353       for (unsigned i = 0; i < boundary1.size (); i++)
00354       {
00355         double error;
00356         Eigen::Vector3d p, tu, tv;
00357         Eigen::Vector3d p0 = boundary1[i];
00358         Eigen::Vector2d params1, params2;
00359 
00360         switch (param.type)
00361         {
00362           case COMMON_BOUNDARY_POINT_MEAN:
00363             p = commonBoundaryPoint1 (*nurbs1, *nurbs2, params1, params2, p0, param.com_iter, error, param.accuracy);
00364             break;
00365           case COMMON_BOUNDARY_POINT_TANGENTS:
00366             p = commonBoundaryPoint2 (*nurbs1, *nurbs2, params1, params2, p0, param.com_iter, error, param.accuracy);
00367             break;
00368           case COMMON_BOUNDARY_POINT_PLANES:
00369             p = commonBoundaryPoint3 (*nurbs1, *nurbs2, params1, params2, p0, param.com_iter, error, param.accuracy);
00370             break;
00371           case CLOSEST_POINTS_INTERIOR:
00372             params1 = FittingSurface::findClosestElementMidPoint (*nurbs2, p0);
00373             FittingSurface::inverseMapping (*nurbs2, p0, params1, error, p, tu, tv, param.com_iter, param.accuracy, true);
00374             break;
00375           case CLOSEST_POINTS_BOUNDARY:
00376             FittingSurface::inverseMappingBoundary (*nurbs2, p0, error, p, tu, tv, param.com_iter, param.accuracy, true);
00377             break;
00378         }
00379 
00380         double dist = (p - p0).norm ();
00381         if (error < param.max_error && dist < param.max_dist)
00382         {
00383           data_list[n1].boundary.push_back (p);
00384           data_list[n2].boundary.push_back (p);
00385         }
00386       }
00387 
00388     } // for each other nurbs
00389 
00390     // nurbs fitting
00391     FittingSurface fit (&data_list[n1], nurbs_list[n1]);
00392     FittingSurface::Parameter paramFP (1.0, param.smoothness, 0.0, 1.0, param.smoothness, 0.0);
00393 
00394     std::vector<double> wBnd, wInt;
00395     for (unsigned i = 0; i < data_list[n1].boundary.size (); i++)
00396       data_list[n1].boundary_weight.push_back (param.boundary_weight);
00397     for (unsigned i = 0; i < data_list[n1].interior.size (); i++)
00398       data_list[n1].interior_weight.push_back (param.interior_weight);
00399 
00400     for (unsigned i = 0; i < param.fit_iter; i++)
00401     {
00402       fit.assemble (paramFP);
00403       fit.solve ();
00404     }
00405     nurbs_list[n1] = fit.m_nurbs;
00406 
00407   } // for each nurbs
00408 
00409 }


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