fitting_surface_tdm.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 <stdexcept>
00039 #include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
00040 
00041 using namespace pcl;
00042 using namespace on_nurbs;
00043 using namespace Eigen;
00044 
00045 FittingSurfaceTDM::FittingSurfaceTDM (NurbsDataSurface *data, const ON_NurbsSurface &ns) :
00046   FittingSurface (data, ns)
00047 {
00048 }
00049 FittingSurfaceTDM::FittingSurfaceTDM (int order, NurbsDataSurface *data, Eigen::Vector3d z) :
00050   FittingSurface (order, data, z)
00051 {
00052 }
00053 
00054 void
00055 FittingSurfaceTDM::assemble (ParameterTDM param)
00056 {
00057   int nBnd = static_cast<int> (m_data->boundary.size ());
00058   int nInt = static_cast<int> (m_data->interior.size ());
00059   int nCurInt = param.regularisation_resU * param.regularisation_resV;
00060   int nCurBnd = 2 * param.regularisation_resU + 2 * param.regularisation_resV;
00061   int nCageReg = (m_nurbs.CVCount (0) - 2) * (m_nurbs.CVCount (1) - 2);
00062   int nCageRegBnd = 2 * (m_nurbs.CVCount (0) - 1) + 2 * (m_nurbs.CVCount (1) - 1);
00063 
00064   if (param.boundary_weight <= 0.0)
00065     nBnd = 0;
00066   if (param.interior_weight <= 0.0)
00067     nInt = 0;
00068   if (param.boundary_regularisation <= 0.0)
00069     nCurBnd = 0;
00070   if (param.interior_regularisation <= 0.0)
00071     nCurInt = 0;
00072   if (param.interior_smoothness <= 0.0)
00073     nCageReg = 0;
00074   if (param.boundary_smoothness <= 0.0)
00075     nCageRegBnd = 0;
00076 
00077   int ncp = m_nurbs.CVCount (0) * m_nurbs.CVCount (1);
00078   int nrows = nBnd + nInt + nCurInt + nCurBnd + nCageReg + nCageRegBnd;
00079 
00080   m_solver.assign (3 * nrows, 3 * ncp, 1);
00081 
00082   unsigned row = 0;
00083 
00084   // boundary points should lie on edges of surface
00085   if (nBnd > 0)
00086     assembleBoundary (param.boundary_weight, param.boundary_tangent_weight, row);
00087 
00088   // interior points should lie on surface
00089   if (nInt > 0)
00090     assembleInterior (param.interior_weight, param.interior_tangent_weight, row);
00091 
00092   // cage regularisation
00093   if (nCageReg > 0)
00094     addCageInteriorRegularisation (param.interior_smoothness, row);
00095 
00096   if (nCageRegBnd > 0)
00097   {
00098     addCageBoundaryRegularisation (param.boundary_smoothness, NORTH, row);
00099     addCageBoundaryRegularisation (param.boundary_smoothness, SOUTH, row);
00100     addCageBoundaryRegularisation (param.boundary_smoothness, WEST, row);
00101     addCageBoundaryRegularisation (param.boundary_smoothness, EAST, row);
00102     addCageCornerRegularisation (param.boundary_smoothness * 2.0, row);
00103   }
00104 }
00105 
00106 void
00107 FittingSurfaceTDM::solve (double damp)
00108 {
00109   if (m_solver.solve ())
00110     updateSurf (damp);
00111 }
00112 
00113 void
00114 FittingSurfaceTDM::updateSurf (double damp)
00115 {
00116   int ncp = m_nurbs.CVCount (0) * m_nurbs.CVCount (1);
00117 
00118   for (int A = 0; A < ncp; A++)
00119   {
00120 
00121     int I = gl2gr (A);
00122     int J = gl2gc (A);
00123 
00124     ON_3dPoint cp_prev;
00125     m_nurbs.GetCV (I, J, cp_prev);
00126 
00127     ON_3dPoint cp;
00128     cp.x = cp_prev.x + damp * (m_solver.x (3 * A + 0, 0) - cp_prev.x);
00129     cp.y = cp_prev.y + damp * (m_solver.x (3 * A + 1, 0) - cp_prev.y);
00130     cp.z = cp_prev.z + damp * (m_solver.x (3 * A + 2, 0) - cp_prev.z);
00131 
00132     m_nurbs.SetCV (I, J, cp);
00133 
00134   }
00135 
00136 }
00137 
00138 void
00139 FittingSurfaceTDM::assembleInterior (double wInt, double wTangent, unsigned &row)
00140 {
00141   m_data->interior_line_start.clear ();
00142   m_data->interior_line_end.clear ();
00143   m_data->interior_error.clear ();
00144   m_data->interior_normals.clear ();
00145   unsigned nInt = static_cast<unsigned> (m_data->interior.size ());
00146   for (unsigned p = 0; p < nInt; p++)
00147   {
00148     Vector3d &pcp = m_data->interior[p];
00149 
00150     // inverse mapping
00151     Vector2d params;
00152     Vector3d pt, tu, tv, n;
00153     double error;
00154     if (p < m_data->interior_param.size ())
00155     {
00156       params = inverseMapping (m_nurbs, pcp, m_data->interior_param[p], error, pt, tu, tv, in_max_steps, in_accuracy);
00157       m_data->interior_param[p] = params;
00158     }
00159     else
00160     {
00161       params = FittingSurface::findClosestElementMidPoint (m_nurbs, pcp);
00162       params = inverseMapping (m_nurbs, pcp, params, error, pt, tu, tv, in_max_steps, in_accuracy);
00163       m_data->interior_param.push_back (params);
00164     }
00165     m_data->interior_error.push_back (error);
00166 
00167     tu.normalize ();
00168     tv.normalize ();
00169     n = tu.cross (tv);
00170 
00171     m_data->interior_normals.push_back (n);
00172     m_data->interior_line_start.push_back (pcp);
00173     m_data->interior_line_end.push_back (pt);
00174 
00175     double w (wInt);
00176     if (p < m_data->interior_weight.size ())
00177       w = m_data->interior_weight[p];
00178 
00179     addPointConstraint (m_data->interior_param[p], m_data->interior[p], n, tu, tv, wTangent, w, row);
00180   }
00181 }
00182 
00183 void
00184 FittingSurfaceTDM::assembleBoundary (double wBnd, double wTangent, unsigned &row)
00185 {
00186   m_data->boundary_line_start.clear ();
00187   m_data->boundary_line_end.clear ();
00188   m_data->boundary_error.clear ();
00189   m_data->boundary_normals.clear ();
00190   unsigned nBnd = static_cast<unsigned> (m_data->boundary.size ());
00191   for (unsigned p = 0; p < nBnd; p++)
00192   {
00193     Vector3d &pcp = m_data->boundary[p];
00194 
00195     double error;
00196     Vector3d pt, tu, tv, n;
00197     Vector2d params = inverseMappingBoundary (m_nurbs, pcp, error, pt, tu, tv, in_max_steps, in_accuracy);
00198     m_data->boundary_error.push_back (error);
00199 
00200     if (p < m_data->boundary_param.size ())
00201     {
00202       m_data->boundary_param[p] = params;
00203     }
00204     else
00205     {
00206       m_data->boundary_param.push_back (params);
00207     }
00208 
00209     tu.normalize ();
00210     tv.normalize ();
00211     n = tu.cross (tv);
00212 
00213     m_data->boundary_normals.push_back (n);
00214     m_data->boundary_line_start.push_back (pcp);
00215     m_data->boundary_line_end.push_back (pt);
00216 
00217     double w (wBnd);
00218     if (p < m_data->boundary_weight.size ())
00219       w = m_data->boundary_weight[p];
00220 
00221     addPointConstraint (m_data->boundary_param[p], m_data->boundary[p], n, tu, tv, wTangent, w, row);
00222   }
00223 }
00224 
00225 void
00226 FittingSurfaceTDM::addPointConstraint (const Eigen::Vector2d &params, const Eigen::Vector3d &p,
00227                                        const Eigen::Vector3d &n, const Eigen::Vector3d &tu, const Eigen::Vector3d &tv,
00228                                        double tangent_weight, double weight, unsigned &row)
00229 {
00230   double *N0 = new double[m_nurbs.Order (0) * m_nurbs.Order (0)];
00231   double *N1 = new double[m_nurbs.Order (1) * m_nurbs.Order (1)];
00232 
00233   int E = ON_NurbsSpanIndex (m_nurbs.Order(0), m_nurbs.CVCount (0), m_nurbs.m_knot[0], params (0), 0, 0);
00234   int F = ON_NurbsSpanIndex (m_nurbs.Order(1), m_nurbs.CVCount (1), m_nurbs.m_knot[1], params (1), 0, 0);
00235 
00236   ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E, params (0), N0);
00237   ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F, params (1), N1);
00238 
00239   double wt = tangent_weight;
00240   Eigen::Vector3d td = n + wt * tu + wt * tv;
00241 
00242   m_solver.f (row + 0, 0, td (0) * p (0) * weight);
00243   m_solver.f (row + 1, 0, td (1) * p (1) * weight);
00244   m_solver.f (row + 2, 0, td (2) * p (2) * weight);
00245 
00246   for (int i = 0; i < m_nurbs.Order (0); i++)
00247   {
00248     for (int j = 0; j < m_nurbs.Order (1); j++)
00249     {
00250 
00251       double val = N0[i] * N1[j] * weight;
00252       unsigned ci = 3 * lrc2gl (E, F, i, j);
00253       m_solver.K (row + 0, ci + 0, td (0) * val);
00254       m_solver.K (row + 1, ci + 1, td (1) * val);
00255       m_solver.K (row + 2, ci + 2, td (2) * val);
00256 
00257     } // j
00258   } // i
00259 
00260   row += 3;
00261 
00262   delete [] N1;
00263   delete [] N0;
00264 }
00265 
00266 void
00267 FittingSurfaceTDM::addCageInteriorRegularisation (double weight, unsigned &row)
00268 {
00269   for (int i = 1; i < (m_nurbs.CVCount (0) - 1); i++)
00270   {
00271     for (int j = 1; j < (m_nurbs.CVCount (1) - 1); j++)
00272     {
00273 
00274       //      m_solver.f(row + 0, 0, 0.0);
00275       //      m_solver.f(row + 1, 0, 0.0);
00276       //      m_solver.f(row + 2, 0, 0.0);
00277 
00278       m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -4.0 * weight);
00279       m_solver.K (row + 0, 3 * grc2gl (i + 0, j - 1) + 0, 1.0 * weight);
00280       m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 1) + 0, 1.0 * weight);
00281       m_solver.K (row + 0, 3 * grc2gl (i - 1, j + 0) + 0, 1.0 * weight);
00282       m_solver.K (row + 0, 3 * grc2gl (i + 1, j + 0) + 0, 1.0 * weight);
00283 
00284       m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -4.0 * weight);
00285       m_solver.K (row + 1, 3 * grc2gl (i + 0, j - 1) + 1, 1.0 * weight);
00286       m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 1) + 1, 1.0 * weight);
00287       m_solver.K (row + 1, 3 * grc2gl (i - 1, j + 0) + 1, 1.0 * weight);
00288       m_solver.K (row + 1, 3 * grc2gl (i + 1, j + 0) + 1, 1.0 * weight);
00289 
00290       m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -4.0 * weight);
00291       m_solver.K (row + 2, 3 * grc2gl (i + 0, j - 1) + 2, 1.0 * weight);
00292       m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 1) + 2, 1.0 * weight);
00293       m_solver.K (row + 2, 3 * grc2gl (i - 1, j + 0) + 2, 1.0 * weight);
00294       m_solver.K (row + 2, 3 * grc2gl (i + 1, j + 0) + 2, 1.0 * weight);
00295 
00296       row += 3;
00297     }
00298   }
00299 }
00300 
00301 void
00302 FittingSurfaceTDM::addCageBoundaryRegularisation (double weight, int side, unsigned &row)
00303 {
00304   int i = 0;
00305   int j = 0;
00306 
00307   switch (side)
00308   {
00309     case SOUTH:
00310       j = m_nurbs.CVCount (1) - 1;
00311     case NORTH:
00312       for (i = 1; i < (m_nurbs.CVCount (0) - 1); i++)
00313       {
00314 
00315         //      m_solver.f(row + 0, 0, 0.0);
00316         //      m_solver.f(row + 1, 0, 0.0);
00317         //      m_solver.f(row + 2, 0, 0.0);
00318 
00319         m_solver.K (row + 0, 3 * grc2gl (i + 0, j) + 0, -2.0 * weight);
00320         m_solver.K (row + 0, 3 * grc2gl (i - 1, j) + 0, 1.0 * weight);
00321         m_solver.K (row + 0, 3 * grc2gl (i + 1, j) + 0, 1.0 * weight);
00322 
00323         m_solver.K (row + 1, 3 * grc2gl (i + 0, j) + 1, -2.0 * weight);
00324         m_solver.K (row + 1, 3 * grc2gl (i - 1, j) + 1, 1.0 * weight);
00325         m_solver.K (row + 1, 3 * grc2gl (i + 1, j) + 1, 1.0 * weight);
00326 
00327         m_solver.K (row + 2, 3 * grc2gl (i + 0, j) + 2, -2.0 * weight);
00328         m_solver.K (row + 2, 3 * grc2gl (i - 1, j) + 2, 1.0 * weight);
00329         m_solver.K (row + 2, 3 * grc2gl (i + 1, j) + 2, 1.0 * weight);
00330 
00331         row += 3;
00332       }
00333       break;
00334 
00335     case EAST:
00336       i = m_nurbs.CVCount (0) - 1;
00337     case WEST:
00338       for (j = 1; j < (m_nurbs.CVCount (1) - 1); j++)
00339       {
00340 
00341         //      m_solver.f(row + 0, 0, 0.0);
00342         //      m_solver.f(row + 1, 0, 0.0);
00343         //      m_solver.f(row + 2, 0, 0.0);
00344 
00345         m_solver.K (row + 0, 3 * grc2gl (i, j + 0) + 0, -2.0 * weight);
00346         m_solver.K (row + 0, 3 * grc2gl (i, j - 1) + 0, 1.0 * weight);
00347         m_solver.K (row + 0, 3 * grc2gl (i, j + 1) + 0, 1.0 * weight);
00348 
00349         m_solver.K (row + 1, 3 * grc2gl (i, j + 0) + 1, -2.0 * weight);
00350         m_solver.K (row + 1, 3 * grc2gl (i, j - 1) + 1, 1.0 * weight);
00351         m_solver.K (row + 1, 3 * grc2gl (i, j + 1) + 1, 1.0 * weight);
00352 
00353         m_solver.K (row + 2, 3 * grc2gl (i, j + 0) + 2, -2.0 * weight);
00354         m_solver.K (row + 2, 3 * grc2gl (i, j - 1) + 2, 1.0 * weight);
00355         m_solver.K (row + 2, 3 * grc2gl (i, j + 1) + 2, 1.0 * weight);
00356 
00357         row += 3;
00358       }
00359       break;
00360   }
00361 }
00362 
00363 void
00364 FittingSurfaceTDM::addCageCornerRegularisation (double weight, unsigned &row)
00365 {
00366   { // NORTH-WEST
00367     int i = 0;
00368     int j = 0;
00369 
00370     //    m_solver.f(row + 0, 0, 0.0);
00371     //    m_solver.f(row + 1, 0, 0.0);
00372     //    m_solver.f(row + 2, 0, 0.0);
00373 
00374     m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00375     m_solver.K (row + 0, 3 * grc2gl (i + 1, j + 0) + 0, 1.0 * weight);
00376     m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 1) + 0, 1.0 * weight);
00377 
00378     m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00379     m_solver.K (row + 1, 3 * grc2gl (i + 1, j + 0) + 1, 1.0 * weight);
00380     m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 1) + 1, 1.0 * weight);
00381 
00382     m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00383     m_solver.K (row + 2, 3 * grc2gl (i + 1, j + 0) + 2, 1.0 * weight);
00384     m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 1) + 2, 1.0 * weight);
00385 
00386     row += 3;
00387 
00388   }
00389 
00390   { // NORTH-EAST
00391     int i = m_nurbs.CVCount (0) - 1;
00392     int j = 0;
00393 
00394     //    m_solver.f(row + 0, 0, 0.0);
00395     //    m_solver.f(row + 1, 0, 0.0);
00396     //    m_solver.f(row + 2, 0, 0.0);
00397 
00398     m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00399     m_solver.K (row + 0, 3 * grc2gl (i - 1, j + 0) + 0, 1.0 * weight);
00400     m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 1) + 0, 1.0 * weight);
00401 
00402     m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00403     m_solver.K (row + 1, 3 * grc2gl (i - 1, j + 0) + 1, 1.0 * weight);
00404     m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 1) + 1, 1.0 * weight);
00405 
00406     m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00407     m_solver.K (row + 2, 3 * grc2gl (i - 1, j + 0) + 2, 1.0 * weight);
00408     m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 1) + 2, 1.0 * weight);
00409 
00410     row += 3;
00411   }
00412 
00413   { // SOUTH-EAST
00414     int i = m_nurbs.CVCount (0) - 1;
00415     int j = m_nurbs.CVCount (1) - 1;
00416 
00417     //    m_solver.f(row + 0, 0, 0.0);
00418     //    m_solver.f(row + 1, 0, 0.0);
00419     //    m_solver.f(row + 2, 0, 0.0);
00420 
00421     m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00422     m_solver.K (row + 0, 3 * grc2gl (i - 1, j + 0) + 0, 1.0 * weight);
00423     m_solver.K (row + 0, 3 * grc2gl (i + 0, j - 1) + 0, 1.0 * weight);
00424 
00425     m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00426     m_solver.K (row + 1, 3 * grc2gl (i - 1, j + 0) + 1, 1.0 * weight);
00427     m_solver.K (row + 1, 3 * grc2gl (i + 0, j - 1) + 1, 1.0 * weight);
00428 
00429     m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00430     m_solver.K (row + 2, 3 * grc2gl (i - 1, j + 0) + 2, 1.0 * weight);
00431     m_solver.K (row + 2, 3 * grc2gl (i + 0, j - 1) + 2, 1.0 * weight);
00432 
00433     row += 3;
00434   }
00435 
00436   { // SOUTH-WEST
00437     int i = 0;
00438     int j = m_nurbs.CVCount (1) - 1;
00439 
00440     //    m_solver.f(row + 0, 0, 0.0);
00441     //    m_solver.f(row + 1, 0, 0.0);
00442     //    m_solver.f(row + 2, 0, 0.0);
00443 
00444     m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00445     m_solver.K (row + 0, 3 * grc2gl (i + 1, j + 0) + 0, 1.0 * weight);
00446     m_solver.K (row + 0, 3 * grc2gl (i + 0, j - 1) + 0, 1.0 * weight);
00447 
00448     m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00449     m_solver.K (row + 1, 3 * grc2gl (i + 1, j + 0) + 1, 1.0 * weight);
00450     m_solver.K (row + 1, 3 * grc2gl (i + 0, j - 1) + 1, 1.0 * weight);
00451 
00452     m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00453     m_solver.K (row + 2, 3 * grc2gl (i + 1, j + 0), 1.0 * weight);
00454     m_solver.K (row + 2, 3 * grc2gl (i + 0, j - 1) + 2 + 2, 1.0 * weight);
00455 
00456     row += 3;
00457   }
00458 
00459 }


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